Establish handlers on the stack
Condition handlers are functions established on the evaluation
stack (see ctxt_stack()
) that are called by R when a condition is
signalled (see cnd_signal()
and abort()
for two common signal
functions). They come in two types:
Exiting handlers aborts all code currently run between
with_handlers()
and the point where the condition has been
raised. with_handlers()
passes the return value of the handler
to its caller.
Calling handlers, which are executed from inside the signalling
functions. Their return values are ignored, only their side
effects matters. Valid side effects are writing a log message, or
jumping out of the signalling context by invoking a restart or using return_from()
. If the raised
condition was an error, this interrupts the aborting process.
If a calling handler returns normally, it effectively declines to handle the condition and other handlers on the stack (calling or exiting) are given a chance to handle the condition.
Handlers are exiting by default, use calling()
to create a
calling handler.
with_handlers(.expr, ...) calling(handler)
.expr |
An expression to execute in a context where new handlers are established. The underscored version takes a quoted expression or a quoted formula. |
... |
<dynamic> Named handlers. These should be
functions of one argument, or formula functions.
The handlers are considered exiting by default, use |
handler |
A handler function that takes a condition as
argument. This is passed to |
exiting()
is soft-deprecated as of rlang
0.4.0 because with_handlers()
now treats handlers as exiting by
default.
# Signal a condition with signal(): fn <- function() { g() cat("called?\n") "fn() return value" } g <- function() { h() cat("called?\n") } h <- function() { signal("A foobar condition occurred", "foo") cat("called?\n") } # Exiting handlers jump to with_handlers() before being # executed. Their return value is handed over: handler <- function(c) "handler return value" with_handlers(fn(), foo = handler) # Calling handlers are called in turn and their return value is # ignored. Returning just means they are declining to take charge of # the condition. However, they can produce side-effects such as # displaying a message: some_handler <- function(c) cat("some handler!\n") other_handler <- function(c) cat("other handler!\n") with_handlers(fn(), foo = calling(some_handler), foo = calling(other_handler)) # If a calling handler jumps to an earlier context, it takes # charge of the condition and no other handler gets a chance to # deal with it. The canonical way of transferring control is by # jumping to a restart. See with_restarts() and restarting() # documentation for more on this: exiting_handler <- function(c) rst_jump("rst_foo") fn2 <- function() { with_restarts(g(), rst_foo = function() "restart value") } with_handlers(fn2(), foo = calling(exiting_handler), foo = calling(other_handler))
Please choose more modern alternatives, such as Google Chrome or Mozilla Firefox.