Become an expert in R — Interactive courses, Cheat Sheets, certificates and more!
Get Started for Free

with_restarts

Establish a restart point on the stack


Description

Questioning lifecycle

Restart points are named functions that are established with with_restarts(). Once established, you can interrupt the normal execution of R code, jump to the restart, and resume execution from there. Each restart is established along with a restart function that is executed after the jump and that provides a return value from the establishing point (i.e., a return value for with_restarts()).

Usage

with_restarts(.expr, ...)

Arguments

.expr

An expression to execute with new restarts established on the stack. This argument is passed by expression and supports unquoting. It is evaluated in a context where restarts are established.

...

<dynamic> Named restart functions. The name is taken as the restart name and the function is executed after the jump.

Details

Restarts are not the only way of jumping to a previous call frame (see return_from() or return_to()). However, they have the advantage of being callable by name once established.

Life cycle

All the restart functions are in the questioning stage. It is not clear yet whether we want to recommend restarts as a style of programming in R.

See Also

return_from() and return_to() for a more flexible way of performing a non-local jump to an arbitrary call frame.

Examples

# Restarts are not the only way to jump to a previous frame, but
# they have the advantage of being callable by name:
fn <- function() with_restarts(g(), my_restart = function() "returned")
g <- function() h()
h <- function() { rst_jump("my_restart"); "not returned" }
fn()

# Whereas a non-local return requires to manually pass the calling
# frame to the return function:
fn <- function() g(current_env())
g <- function(env) h(env)
h <- function(env) { return_from(env, "returned"); "not returned" }
fn()


# rst_maybe_jump() checks that a restart exists before trying to jump:
fn <- function() {
  g()
  cat("will this be called?\n")
}
g <- function() {
  rst_maybe_jump("my_restart")
  cat("will this be called?\n")
}

# Here no restart are on the stack:
fn()

# If a restart point called `my_restart` was established on the
# stack before calling fn(), the control flow will jump there:
rst <- function() {
  cat("restarting...\n")
  "return value"
}
with_restarts(fn(), my_restart = rst)


# Restarts are particularly useful to provide alternative default
# values when the normal output cannot be computed:

fn <- function(valid_input) {
  if (valid_input) {
    return("normal value")
  }

  # We decide to return the empty string "" as default value. An
  # altenative strategy would be to signal an error. In any case,
  # we want to provide a way for the caller to get a different
  # output. For this purpose, we provide two restart functions that
  # returns alternative defaults:
  restarts <- list(
    rst_empty_chr = function() character(0),
    rst_null = function() NULL
  )

  with_restarts(splice(restarts), .expr = {

    # Signal a typed condition to let the caller know that we are
    # about to return an empty string as default value:
    cnd_signal("default_empty_string")

    # If no jump to with_restarts, return default value:
    ""
  })
}

# Normal value for valid input:
fn(TRUE)

# Default value for bad input:
fn(FALSE)

# Change the default value if you need an empty character vector by
# defining a calling handler that jumps to the restart. It has to
# be calling because exiting handlers jump to the place where they
# are established before being executed, and the restart is not
# defined anymore at that point:
rst_handler <- calling(function(c) rst_jump("rst_empty_chr"))
with_handlers(fn(FALSE), default_empty_string = rst_handler)

# You can use restarting() to create restarting handlers easily:
with_handlers(fn(FALSE), default_empty_string = restarting("rst_null"))

rlang

Functions for Base Types and Core R and 'Tidyverse' Features

v0.4.11
MIT + file LICENSE
Authors
Lionel Henry [aut, cre], Hadley Wickham [aut], mikefc [cph] (Hash implementation based on Mike's xxhashlite), Yann Collet [cph] (Author of the embedded xxHash library), RStudio [cph]
Initial release

We don't support your browser anymore

Please choose more modern alternatives, such as Google Chrome or Mozilla Firefox.