Evaluate an expression in an environment.

expr_eval() is a lightweight version of the base function eval(). It does not accept supplementary data, but it is more efficient and does not clutter the evaluation stack. Technically, expr_eval() is a simple wrapper around the C function Rf_eval().

expr_eval(expr, env = parent.frame())
An expression to evaluate.
The environment in which to evaluate the expression.

base::eval() inserts two call frames in the stack, the second of which features the envir parameter as frame environment. This may unnecessarily clutter the evaluation stack and it can change evaluation semantics with stack sensitive functions in the case where env is an evaluation environment of a stack frame (see eval_stack()). Since the base function eval() creates a new evaluation context with env as frame environment there are actually two contexts with the same evaluation environment on the stack when expr is evaluated. Thus, any command that looks up frames on the stack (stack sensitive functions) may find the parasite frame set up by eval() rather than the original frame targetted by env. As a result, code evaluated with base::eval() does not have the property of stack consistency, and stack sensitive functions like return(), parent.frame() may return misleading results.

See Also


  • expr_eval
# expr_eval() works just like base::eval():
env <- new_env(data = list(foo = "bar"))
expr <- quote(foo)
expr_eval(expr, env)

# To explore the consequences of stack inconsistent semantics, let's
# create a function that evaluates `parent.frame()` deep in the call
# stack, in an environment corresponding to a frame in the middle of
# the stack. For consistency we R's lazy evaluation semantics, we'd
# expect to get the caller of that frame as result:
fn <- function(eval_fn) {
    returned_env = middle(eval_fn),
    actual_env = env()
middle <- function(eval_fn) {
  deep(eval_fn, env())
deep <- function(eval_fn, eval_env) {
  expr <- quote(parent.frame())
  eval_fn(expr, eval_env)

# With expr_eval(), we do get the expected environment:

# But that's not the case with base::eval():

# Another difference of expr_eval() compared to base::eval() is
# that it does not insert parasite frames in the evaluation stack:
get_stack <- quote(identity(eval_stack()))
Documentation reproduced from package rlang, version, License: GPL-3

Community examples

Looks like there are no examples yet.