There are two types of condition handlers: exiting handlers, which are thrown to the place where they have been established (e.g., with_handlers()'s evaluation frame), and local handlers, which are executed in place (e.g., where the condition has been signalled). exiting() and calling() create handlers suitable for with_handlers().





A handler function that takes a condition as argument. This is passed to as_function() and can thus be a formula describing a lambda function.


A subtle point in the R language is that conditions are not thrown, handlers are. base::tryCatch() and with_handlers() actually catch handlers rather than conditions. When a critical condition is signalled with base::stop() or abort(), R inspects the handler stack and looks for a handler that can deal with the condition. If it finds an exiting handler, it throws it to the function that established it (with_handlers()). That is, it interrupts the normal course of evaluation and jumps to with_handlers() evaluation frame (see ctxt_stack()), and only then and there the handler is called. On the other hand, if R finds a calling handler, it executes it locally. The calling handler can choose to handle the condition by jumping out of the frame (see rst_jump() or return_from()). If it returns locally, it declines to handle the condition which is passed to the next relevant handler on the stack. If no handler is found or is able to deal with the critical condition (by jumping out of the frame), R will then jump out of the faulty evaluation frame to top-level, via the abort restart (see rst_abort()).

Life cycle

exiting() is in the questioning stage because with_handlers() now treats handlers as exiting by default.

See also

with_handlers() for examples, restarting() for another kind of calling handler.


# You can supply a function taking a condition as argument: hnd <- exiting(function(c) cat("handled foo\n")) with_handlers(signal("A foobar condition occurred", "foo"), foo = hnd)
#> handled foo
# Or a lambda-formula where "." is bound to the condition: with_handlers(foo = calling(~cat("hello", .$attr, "\n")), { signal("A foobar condition occurred", "foo", attr = "there") "foo" })
#> hello there
#> [1] "foo"