with_handlers {rlang}R Documentation

Establish handlers on the stack

Description

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:

Handlers are exiting by default, use calling() to create a calling handler.

Usage

with_handlers(.expr, ...)

calling(handler)

Arguments

.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 calling() to specify a calling handler.

handler

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.

Life cycle

exiting() is soft-deprecated as of rlang 0.4.0 because with_handlers() now treats handlers as exiting by default.

Examples

# 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))

[Package rlang version 0.4.5 Index]