Call stack information
The eval_
and call_
families of functions provide a replacement
for the base R functions prefixed with sys.
(which are all about
the context stack), as well as for parent.frame()
(which is the
only base R function for querying the call stack). The context
stack includes all R-level evaluation contexts. It is linear in
terms of execution history but due to lazy evaluation it is
potentially nonlinear in terms of call history. The call stack
history, on the other hand, is homogenous.
global_frame() current_frame() ctxt_frame(n = 1) call_frame(n = 1, clean = TRUE) ctxt_depth() call_depth() ctxt_stack(n = NULL, trim = 0) call_stack(n = NULL, clean = TRUE)
n |
The number of frames to go back in the stack. |
clean |
Whether to post-process the call stack to clean
non-standard frames. If |
trim |
The number of layers of intervening frames to trim off
the stack. See |
ctxt_frame()
and call_frame()
return a frame
object
containing the following fields: expr
and env
(call expression
and evaluation environment), pos
and caller_pos
(position of
current frame in the context stack and position of the caller), and
fun
(function of the current frame). ctxt_stack()
and
call_stack()
return a list of all context or call frames on the
stack. Finally, ctxt_depth()
and call_depth()
report the
current context position or the number of calling frames on the
stack.
The base R functions take two sorts of arguments to indicate which
frame to query: which
and n
. The n
argument is
straightforward: it's the number of frames to go down the stack,
with n = 1
referring to the current context. The which
argument
is more complicated and changes meaning for values lower than 1.
For the sake of consistency, the rlang functions all take the
same kind of argument n
. This argument has a single meaning (the
number of frames to go down the stack) and cannot be lower than 1.
Note finally that parent.frame(1)
corresponds to
call_frame(2)$env
, as n = 1
always refers to the current
frame. This makes the _frame()
and _stack()
functions
consistent: ctxt_frame(2)
is the same as ctxt_stack()[[2]]
.
Also, ctxt_depth()
returns one more frame than
base::sys.nframe()
because it counts the global frame. That is
consistent with the _stack()
functions which return the global
frame as well. This way, call_stack(call_depth())
is the same as
global_frame()
.
These functions are soft-deprecated and replaced by trace_back()
.
# Expressions within arguments count as contexts identity(identity(ctxt_depth())) # returns 2 # But they are not part of the call stack because arguments are # evaluated within the calling function (or the global environment # if called at top level) identity(identity(call_depth())) # returns 0 # The context stacks includes all intervening execution frames. The # call stack doesn't: f <- function(x) identity(x) f(f(ctxt_stack())) f(f(call_stack())) g <- function(cmd) cmd() f(g(ctxt_stack)) f(g(call_stack)) # The rlang _stack() functions return a list of frame # objects. Use purrr::transpose() or index a field with # purrr::map()'s to extract a particular field from a stack: # stack <- f(f(call_stack())) # purrr::map(stack, "env") # purrr::transpose(stack)$expr # current_frame() is an alias for ctxt_frame(1) fn <- function() list(current = current_frame(), first = ctxt_frame(1)) fn() # While current_frame() is the top of the stack, global_frame() is # the bottom: fn <- function() { n <- ctxt_depth() ctxt_frame(n) } identical(fn(), global_frame()) # ctxt_stack() returns a stack with all intervening frames. You can # trim layers of intervening frames with the trim argument: identity(identity(ctxt_stack())) identity(identity(ctxt_stack(trim = 1))) # ctxt_stack() is called within fn() with intervening frames: fn <- function(trim) identity(identity(ctxt_stack(trim = trim))) fn(0) # We can trim the first layer of those: fn(1) # The outside intervening frames (at the fn() call site) are still # returned, but can be trimmed as well: identity(identity(fn(1))) identity(identity(fn(2))) g <- function(trim) identity(identity(fn(trim))) g(2) g(3)
Please choose more modern alternatives, such as Google Chrome or Mozilla Firefox.