context | R Documentation |
Programming in R typically involves:
Making a context: assigning values to names.
Performing an action: evaluating an expression relative to a context.
let()
and run()
enable you to treat these procedures as reusable,
composable components.
let()
makes a context: it lazily binds a sequence of ordered
named expressions to a child of a given environment (by default, the
current one).
For instance, in an environment env
where z
is in scope,
let(env, x = 1, y = x + 2, z = x * y * z)
is equivalent to calling
local({ x <- 1 y <- x + 2 z <- x * y * z environment() })
except let()
binds the named expressions lazily (as
promises) and comprehends tidyverse
quasiquotation.
run()
performs an action: it evaluates an expression relative to an
environment (by default, the current one) and, optionally, a sequence of
lazily evaluated ordered named expressions.
For instance, in an environment env
where x
is in scope,
run(env, x + y + z, y = x + 2, z = x * y * z)
is equivalent to calling
local({ y <- x + 2 z <- x * y * z x + y + z })
except run()
, like let()
, binds y
and z
lazily and comprehends
quasiquotation.
let(`_data` = parent.frame(), ...) run(`_data` = parent.frame(), `_expr`, ...)
_data |
Context of named values, namely an environment, list or data
frame; if a list or data frame, it is interpreted as an environment (like
the |
... |
Named expressions. An expression looks up values to the left of
it, and takes precedence over those in |
'_expr' |
Expression to evaluate (“run”). Quasiquotation is supported. |
run()
returns the evaluation of `_expr`
in the combined
environment of `_data`
and ...
.
let()
returns an environment where the bindings in ...
are in scope, as
promises, as if they were assigned from left to right in
a child of the environment defined by `_data`
.
Contexts, as made by let()
, have an advantage over ordinary local
assignments because contexts are both lazy and composable. Like
assignments, the order of named expressions in a context is significant.
For example, you can string together contexts to make larger ones:
foo <- let(a = ., b = a + 2) %>>>% let(c = a + b) %>>>% run(a + b + c) foo(1) #> [1] 8
Earlier bindings can be overriden by later ones:
bar <- foo[1:2] %>>>% # Collect the contexts of 'foo()' let(c = c - 1) %>>>% # Override 'c' run(a + b + c) bar(1) #> [1] 7
Bindings are promises; they are only evaluated on demand:
run(let(x = a_big_expense(), y = "avoid a big expense"), y) #> [1] "avoid a big expense"
“Contexts” as described here should not be confused with “contexts” in R's internal mechanism.
with()
is like run()
, but more limited because it doesn't
support quasiquotation or provide a means to override local bindings.
# Miles-per-gallon of big cars mtcars$mpg[mtcars$cyl == 8 & mtcars$disp > 350] run(mtcars, mpg[cyl == 8 & disp > 350]) run(mtcars, mpg[big_cars], big_cars = cyl == 8 & disp > 350) # 'let()' makes a reusable local context for big cars cars <- let(mtcars, big = cyl == 8 & disp > 350) eval(quote(mpg[big]), cars) # Quoting restricts name lookup to 'cars' run(cars, mpg[big]) # The same, but shorter and more transparent run(cars, wt[big]) mtcars$wt[mtcars$cyl == 8 & mtcars$disp > 350] # Precedence of names is from right to left ("bottom-up"): a <- 1000 run(`_expr` = a + b, a = 1, b = a + 2) # 4: all references are local run(list(a = 1), a + b, b = a + 2) # 4: 'b' references local 'a' run(let(a = 1, b = a + 2), a + b) # 4: 'b' references local 'a' run(let(a = 1, b = a + 2), a + b, a = 0) # 3: latter 'a' takes precedence run(list(a = 1, b = a + 2), a + b) # 1003: 'b' references global 'a' # Bound expressions are lazily evaluated: no error unless 'x' is referenced run(`_expr` = "S'all good, man.", x = stop("!")) run(let(x = stop("!")), "S'all good, man.") let(x = stop("!")) # Environment binding 'x' try(let(x = stop("!"))$x) # Error: ! # Quasiquotation is supported a <- 1 run(let(a = 2), a + !!a) #> [1] 3 run(let(a = 1 + !!a, b = a), c(a, b)) #> [1] 2 2
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.