Capture an expression and evaluation environment.

A powerful feature in R is the ability of capturing the expression supplied in a function call. Once captured, this expression can be inspected and evaluated, possibly within an altered scope environment (for instance a scope where all elements of a data frame are directly accessible). The tricky part of capturing an expression for rescoping purposes is to keep the original evaluation environment accessible so that other variables defined at the call site are available when the expression gets evaluated. It is thus necessary to capture not only the R expression supplied as argument in a function call, but also the evaluation environment of the call site. arg_capture() and dots_capture() make it easy to record this information within formulas.

x, ...
Arguments to capture.

arg_capture() returns a formula; dots_capture() returns a list of formulas, one for each dotted argument.

Non-standard evaluation

The two main purposes for capturing arguments are labelling and rescoping. With labelling, the normal R evaluation rules are kept unchanged. The captured expression is only used to provide default names (or labels) to output elements, such as column names for a function that manipulates data frames or axis labels for a function that creates graphics. In the case of rescoping however, evaluation rules are altered. Functions that capture and rescope arguments are said to use non-standard evaluation, or NSE. The approach we recommend in rlang is to always create two versions of such functions: a NSE version that captures arguments, and another that work with captured arguments with standard evaluation rules (see decorate_nse()). Providing a standard evaluation version simplifies programming tasks. Also, it makes it possible to forward named arguments across function calls (see below). See vignette("nse") for more information on NSE. In addition, note that arg_capture() always interpolates its input to facilitate programming with NSE functions. See interp() and f_quote().

Forwarding arguments

You have to be a bit careful when you pass arguments between introspective functions as only the most immediate call site is captured. For this reason, named arguments should be captured by an NSE function at the outermost level, and then passed around to SE versions that handle pre-captured arguments. See arg_inspect() for another approach to introspecting arguments with which it is possible to capture expressions at the outermost call site. This approach may be harder to reason about and has some limitations. Dots are different from named arguments in that they are implicitly forwarded. Forwarding dots does not create a new call site. The expression is passed on as is. That's why you can easily capture them with substitute(). By the same token, you don't need to capture dots before passing them along in another introspective function. You do need to be a bit careful when you rescope expressions captured from dots because those expressions were not necessarily supplied in the last call frame. In general, the call site of argument passed through dots can be anywhere between the current and global frames. For this reason, it is recommended to always use dots_capture() rather than substitute() and env_caller() or parent.frame(), since the former will encode the appropriate evaluation environments within the formulas.

See Also

arg_expr(), arg_label() and arg_text() provide labelling information in alternative forms.

  • arg_capture
  • dots_capture
# arg_capture() returns a formula:
fn <- function(foo) arg_capture(foo)
fn(a + b)

# Capturing an argument only works for the most direct call:
g <- function(bar) fn(bar)
g(a + b)

# Dots on the other hand are forwarded all the way to
# dots_capture() and can be captured across levels:
fn <- function(...) dots_capture(y = a + b, ...)
fn(z = a + b)

# Note that if you pass a named argument in dots, only the
# expression at the dots call site is captured:
fn <- function(x = a + b) dots_capture(x = x)
Documentation reproduced from package rlang, version, License: GPL-3

Community examples

Looks like there are no examples yet.