Deprecated lifecycle

ctxt_stack() can be tricky to use in real code because all intervening frames are returned with the stack, including those at ctxt_stack() own call site. stack_trim() makes it easy to remove layers of intervening calls.

stack_trim(stack, n = 1)

Arguments

stack

An evaluation stack.

n

The number of call frames (not eval frames) to trim off the top of the stack. In other words, the number of layers of intervening frames to trim.

Life cycle

These functions are deprecated and replaced by trace_back().

Examples

# Intervening frames appear on the evaluation stack: identity(identity(ctxt_stack()))
#> [[1]] #> <frame 35> (33) #> expr: identity(ctxt_stack()) #> env: [local 0x555f43e31ec0] #> #> [[2]] #> <frame 34> (33) #> expr: identity(identity(ctxt_stack())) #> env: [local 0x555f43e31fd8] #> #> [[3]] #> <frame 33> (32) #> expr: eval(expr, envir, enclos) #> env: [local 0x555f46b156c0] #> #> [[4]] #> <frame 32> (22) #> expr: eval(expr, envir, enclos) #> env: [local 0x555f43e32198] #> #> [[5]] #> <frame 31> (22) #> expr: withVisible(eval(expr, envir, enclos)) #> env: [local 0x555f43e323c8] #> #> [[6]] #> <frame 30> (22) #> expr: withCallingHandlers(withVisible(eval(expr, envir, enclos)), warning = wHandler, <...> #> env: [local 0x555f43e329b0] #> #> [[7]] #> <frame 29> (28) #> expr: doTryCatch(return(expr), name, parentenv, handler) #> env: [local 0x555f43e2f0f8] #> #> [[8]] #> <frame 28> (27) #> expr: tryCatchOne(expr, names, parentenv, handlers[[1L]]) #> env: [local 0x555f43e2f440] #> #> [[9]] #> <frame 27> (26) #> expr: tryCatchList(expr, classes, parentenv, handlers) #> env: [local 0x555f43e2f788] #> #> [[10]] #> <frame 26> (25) #> expr: tryCatch(expr, error = function(e) { <...> #> env: [local 0x555f43e2fe50] #> #> [[11]] #> <frame 25> (24) #> expr: try(f, silent = TRUE) #> env: [local 0x555f43e30080] #> #> [[12]] #> <frame 24> (22) #> expr: handle(ev <- withCallingHandlers(withVisible(eval(expr, envir, <...> #> env: [local 0x555f43e30208] #> #> [[13]] #> <frame 23> (22) #> expr: timing_fn(handle(ev <- withCallingHandlers(withVisible(eval(expr, <...> #> env: [local 0x555f43e302e8] #> #> [[14]] #> <frame 22> (21) #> expr: evaluate_call(expr, parsed$src[[i]], envir = envir, enclos = enclos, <...> #> env: [frame 0x555f43e20978] #> #> [[15]] #> <frame 21> (20) #> expr: evaluate::evaluate(x, child_env(env), new_device = TRUE) #> env: [frame 0x555f405102a8] #> #> [[16]] #> <frame 20> (19) #> expr: highlight_examples(code, topic, env = env) #> env: [frame 0x555f40508698] #> #> [[17]] #> <frame 19> (18) #> expr: run_examples(tags$tag_examples[[1]], env = new.env(parent = globalenv()), <...> #> env: [frame 0x555f410aa7d8] #> #> [[18]] #> <frame 18> (17) #> expr: data_reference_topic(topic, pkg, examples = examples, run_dont_run = run_dont_run) #> env: [frame 0x555f418249f8] #> #> [[19]] #> <frame 17> (16) #> expr: .f(.x[[i]], ...) #> env: [frame 0x555f434f8ab0] #> #> [[20]] #> <frame 16> (15) #> expr: purrr::map(topics, build_reference_topic, pkg = pkg, lazy = lazy, <...> #> env: [frame 0x555f3cc9b7f8] #> #> [[21]] #> <frame 15> (14) #> expr: build_reference(pkg, lazy = lazy, examples = examples, run_dont_run = run_dont_run, <...> #> env: [frame 0x555f3ad79698] #> #> [[22]] #> <frame 14> (13) #> expr: build_site_local(pkg = pkg, examples = examples, run_dont_run = run_dont_run, <...> #> env: [frame 0x555f397076c8] #> #> [[23]] #> <frame 13> (12) #> expr: pkgdown::build_site(...) #> env: [frame 0x555f39c40618] #> #> [[24]] #> <frame 12> (0) #> expr: (function (..., crayon_enabled, crayon_colors, pkgdown_internet) <...> #> env: [frame 0x555f39c95938] #> #> [[25]] #> <frame 11> (0) #> expr: (function (what, args, quote = FALSE, envir = parent.frame()) <...> #> env: [frame 0x555f39c94828] #> #> [[26]] #> <frame 10> (0) #> expr: do.call(do.call, c(readRDS("/tmp/RtmpivJ8hr/callr-fun-1c30651e92ec"), <...> #> env: [frame 0x555f3b324c98] #> #> [[27]] #> <frame 9> (0) #> expr: saveRDS(do.call(do.call, c(readRDS("/tmp/RtmpivJ8hr/callr-fun-1c30651e92ec"), <...> #> env: [frame 0x555f3b325018] #> #> [[28]] #> <frame 8> (0) #> expr: withCallingHandlers({ <...> #> env: [frame 0x555f3b321a38] #> #> [[29]] #> <frame 7> (6) #> expr: doTryCatch(return(expr), name, parentenv, handler) #> env: [frame 0x555f3b3220c8] #> #> [[30]] #> <frame 6> (5) #> expr: tryCatchOne(expr, names, parentenv, handlers[[1L]]) #> env: [frame 0x555f3b322410] #> #> [[31]] #> <frame 5> (2) #> expr: tryCatchList(expr, names[-nh], parentenv, handlers[-nh]) #> env: [frame 0x555f3b3227c8] #> #> [[32]] #> <frame 4> (3) #> expr: doTryCatch(return(expr), name, parentenv, handler) #> env: [frame 0x555f3b322d78] #> #> [[33]] #> <frame 3> (2) #> expr: tryCatchOne(tryCatchList(expr, names[-nh], parentenv, handlers[-nh]), <...> #> env: [frame 0x555f3b3230c0] #> #> [[34]] #> <frame 2> (1) #> expr: tryCatchList(expr, classes, parentenv, handlers) #> env: [frame 0x555f3b323408] #> #> [[35]] #> <frame 1> (0) #> expr: tryCatch(withCallingHandlers({ <...> #> env: [frame 0x555f3b31fd10] #> #> [[36]] #> <frame 0> [global] #> expr: NULL #> env: [global] #> #> attr(,"class") #> [1] "ctxt_stack" "stack"
# stack_trim() will trim the first n layers of calls: stack_trim(identity(identity(ctxt_stack())))
#> [[1]] #> <frame 33> (32) #> expr: eval(expr, envir, enclos) #> env: [local 0x555f46b156c0] #> #> [[2]] #> <frame 32> (22) #> expr: eval(expr, envir, enclos) #> env: [local 0x555f443d1058] #> #> [[3]] #> <frame 31> (22) #> expr: withVisible(eval(expr, envir, enclos)) #> env: [local 0x555f443d0e28] #> #> [[4]] #> <frame 30> (22) #> expr: withCallingHandlers(withVisible(eval(expr, envir, enclos)), warning = wHandler, <...> #> env: [local 0x555f443d0878] #> #> [[5]] #> <frame 29> (28) #> expr: doTryCatch(return(expr), name, parentenv, handler) #> env: [local 0x555f443dfbf0] #> #> [[6]] #> <frame 28> (27) #> expr: tryCatchOne(expr, names, parentenv, handlers[[1L]]) #> env: [local 0x555f443df8a8] #> #> [[7]] #> <frame 27> (26) #> expr: tryCatchList(expr, classes, parentenv, handlers) #> env: [local 0x555f443df560] #> #> [[8]] #> <frame 26> (25) #> expr: tryCatch(expr, error = function(e) { <...> #> env: [local 0x555f443dee60] #> #> [[9]] #> <frame 25> (24) #> expr: try(f, silent = TRUE) #> env: [local 0x555f443dec30] #> #> [[10]] #> <frame 24> (22) #> expr: handle(ev <- withCallingHandlers(withVisible(eval(expr, envir, <...> #> env: [local 0x555f443deaa8] #> #> [[11]] #> <frame 23> (22) #> expr: timing_fn(handle(ev <- withCallingHandlers(withVisible(eval(expr, <...> #> env: [local 0x555f443de9c8] #> #> [[12]] #> <frame 22> (21) #> expr: evaluate_call(expr, parsed$src[[i]], envir = envir, enclos = enclos, <...> #> env: [frame 0x555f45f9d7a8] #> #> [[13]] #> <frame 21> (20) #> expr: evaluate::evaluate(x, child_env(env), new_device = TRUE) #> env: [frame 0x555f405102a8] #> #> [[14]] #> <frame 20> (19) #> expr: highlight_examples(code, topic, env = env) #> env: [frame 0x555f40508698] #> #> [[15]] #> <frame 19> (18) #> expr: run_examples(tags$tag_examples[[1]], env = new.env(parent = globalenv()), <...> #> env: [frame 0x555f410aa7d8] #> #> [[16]] #> <frame 18> (17) #> expr: data_reference_topic(topic, pkg, examples = examples, run_dont_run = run_dont_run) #> env: [frame 0x555f418249f8] #> #> [[17]] #> <frame 17> (16) #> expr: .f(.x[[i]], ...) #> env: [frame 0x555f434f8ab0] #> #> [[18]] #> <frame 16> (15) #> expr: purrr::map(topics, build_reference_topic, pkg = pkg, lazy = lazy, <...> #> env: [frame 0x555f3cc9b7f8] #> #> [[19]] #> <frame 15> (14) #> expr: build_reference(pkg, lazy = lazy, examples = examples, run_dont_run = run_dont_run, <...> #> env: [frame 0x555f3ad79698] #> #> [[20]] #> <frame 14> (13) #> expr: build_site_local(pkg = pkg, examples = examples, run_dont_run = run_dont_run, <...> #> env: [frame 0x555f397076c8] #> #> [[21]] #> <frame 13> (12) #> expr: pkgdown::build_site(...) #> env: [frame 0x555f39c40618] #> #> [[22]] #> <frame 12> (0) #> expr: (function (..., crayon_enabled, crayon_colors, pkgdown_internet) <...> #> env: [frame 0x555f39c95938] #> #> [[23]] #> <frame 11> (0) #> expr: (function (what, args, quote = FALSE, envir = parent.frame()) <...> #> env: [frame 0x555f39c94828] #> #> [[24]] #> <frame 10> (0) #> expr: do.call(do.call, c(readRDS("/tmp/RtmpivJ8hr/callr-fun-1c30651e92ec"), <...> #> env: [frame 0x555f3b324c98] #> #> [[25]] #> <frame 9> (0) #> expr: saveRDS(do.call(do.call, c(readRDS("/tmp/RtmpivJ8hr/callr-fun-1c30651e92ec"), <...> #> env: [frame 0x555f3b325018] #> #> [[26]] #> <frame 8> (0) #> expr: withCallingHandlers({ <...> #> env: [frame 0x555f3b321a38] #> #> [[27]] #> <frame 7> (6) #> expr: doTryCatch(return(expr), name, parentenv, handler) #> env: [frame 0x555f3b3220c8] #> #> [[28]] #> <frame 6> (5) #> expr: tryCatchOne(expr, names, parentenv, handlers[[1L]]) #> env: [frame 0x555f3b322410] #> #> [[29]] #> <frame 5> (2) #> expr: tryCatchList(expr, names[-nh], parentenv, handlers[-nh]) #> env: [frame 0x555f3b3227c8] #> #> [[30]] #> <frame 4> (3) #> expr: doTryCatch(return(expr), name, parentenv, handler) #> env: [frame 0x555f3b322d78] #> #> [[31]] #> <frame 3> (2) #> expr: tryCatchOne(tryCatchList(expr, names[-nh], parentenv, handlers[-nh]), <...> #> env: [frame 0x555f3b3230c0] #> #> [[32]] #> <frame 2> (1) #> expr: tryCatchList(expr, classes, parentenv, handlers) #> env: [frame 0x555f3b323408] #> #> [[33]] #> <frame 1> (0) #> expr: tryCatch(withCallingHandlers({ <...> #> env: [frame 0x555f3b31fd10] #> #> [[34]] #> <frame 0> [global] #> expr: NULL #> env: [global] #> #> attr(,"class") #> [1] "ctxt_stack" "stack"
# Note that it also takes care of calls intervening at its own call # site: identity(identity( stack_trim(identity(identity(ctxt_stack()))) ))
#> [[1]] #> <frame 33> (32) #> expr: eval(expr, envir, enclos) #> env: [local 0x555f46b156c0] #> #> [[2]] #> <frame 32> (22) #> expr: eval(expr, envir, enclos) #> env: [local 0x555f417e9be8] #> #> [[3]] #> <frame 31> (22) #> expr: withVisible(eval(expr, envir, enclos)) #> env: [local 0x555f417e99b8] #> #> [[4]] #> <frame 30> (22) #> expr: withCallingHandlers(withVisible(eval(expr, envir, enclos)), warning = wHandler, <...> #> env: [local 0x555f417ed190] #> #> [[5]] #> <frame 29> (28) #> expr: doTryCatch(return(expr), name, parentenv, handler) #> env: [local 0x555f417ec780] #> #> [[6]] #> <frame 28> (27) #> expr: tryCatchOne(expr, names, parentenv, handlers[[1L]]) #> env: [local 0x555f417ec390] #> #> [[7]] #> <frame 27> (26) #> expr: tryCatchList(expr, classes, parentenv, handlers) #> env: [local 0x555f417ebfa0] #> #> [[8]] #> <frame 26> (25) #> expr: tryCatch(expr, error = function(e) { <...> #> env: [local 0x555f417eb830] #> #> [[9]] #> <frame 25> (24) #> expr: try(f, silent = TRUE) #> env: [local 0x555f4383bdd0] #> #> [[10]] #> <frame 24> (22) #> expr: handle(ev <- withCallingHandlers(withVisible(eval(expr, envir, <...> #> env: [local 0x555f4383bc48] #> #> [[11]] #> <frame 23> (22) #> expr: timing_fn(handle(ev <- withCallingHandlers(withVisible(eval(expr, <...> #> env: [local 0x555f4383bb68] #> #> [[12]] #> <frame 22> (21) #> expr: evaluate_call(expr, parsed$src[[i]], envir = envir, enclos = enclos, <...> #> env: [frame 0x555f40e3c350] #> #> [[13]] #> <frame 21> (20) #> expr: evaluate::evaluate(x, child_env(env), new_device = TRUE) #> env: [frame 0x555f405102a8] #> #> [[14]] #> <frame 20> (19) #> expr: highlight_examples(code, topic, env = env) #> env: [frame 0x555f40508698] #> #> [[15]] #> <frame 19> (18) #> expr: run_examples(tags$tag_examples[[1]], env = new.env(parent = globalenv()), <...> #> env: [frame 0x555f410aa7d8] #> #> [[16]] #> <frame 18> (17) #> expr: data_reference_topic(topic, pkg, examples = examples, run_dont_run = run_dont_run) #> env: [frame 0x555f418249f8] #> #> [[17]] #> <frame 17> (16) #> expr: .f(.x[[i]], ...) #> env: [frame 0x555f434f8ab0] #> #> [[18]] #> <frame 16> (15) #> expr: purrr::map(topics, build_reference_topic, pkg = pkg, lazy = lazy, <...> #> env: [frame 0x555f3cc9b7f8] #> #> [[19]] #> <frame 15> (14) #> expr: build_reference(pkg, lazy = lazy, examples = examples, run_dont_run = run_dont_run, <...> #> env: [frame 0x555f3ad79698] #> #> [[20]] #> <frame 14> (13) #> expr: build_site_local(pkg = pkg, examples = examples, run_dont_run = run_dont_run, <...> #> env: [frame 0x555f397076c8] #> #> [[21]] #> <frame 13> (12) #> expr: pkgdown::build_site(...) #> env: [frame 0x555f39c40618] #> #> [[22]] #> <frame 12> (0) #> expr: (function (..., crayon_enabled, crayon_colors, pkgdown_internet) <...> #> env: [frame 0x555f39c95938] #> #> [[23]] #> <frame 11> (0) #> expr: (function (what, args, quote = FALSE, envir = parent.frame()) <...> #> env: [frame 0x555f39c94828] #> #> [[24]] #> <frame 10> (0) #> expr: do.call(do.call, c(readRDS("/tmp/RtmpivJ8hr/callr-fun-1c30651e92ec"), <...> #> env: [frame 0x555f3b324c98] #> #> [[25]] #> <frame 9> (0) #> expr: saveRDS(do.call(do.call, c(readRDS("/tmp/RtmpivJ8hr/callr-fun-1c30651e92ec"), <...> #> env: [frame 0x555f3b325018] #> #> [[26]] #> <frame 8> (0) #> expr: withCallingHandlers({ <...> #> env: [frame 0x555f3b321a38] #> #> [[27]] #> <frame 7> (6) #> expr: doTryCatch(return(expr), name, parentenv, handler) #> env: [frame 0x555f3b3220c8] #> #> [[28]] #> <frame 6> (5) #> expr: tryCatchOne(expr, names, parentenv, handlers[[1L]]) #> env: [frame 0x555f3b322410] #> #> [[29]] #> <frame 5> (2) #> expr: tryCatchList(expr, names[-nh], parentenv, handlers[-nh]) #> env: [frame 0x555f3b3227c8] #> #> [[30]] #> <frame 4> (3) #> expr: doTryCatch(return(expr), name, parentenv, handler) #> env: [frame 0x555f3b322d78] #> #> [[31]] #> <frame 3> (2) #> expr: tryCatchOne(tryCatchList(expr, names[-nh], parentenv, handlers[-nh]), <...> #> env: [frame 0x555f3b3230c0] #> #> [[32]] #> <frame 2> (1) #> expr: tryCatchList(expr, classes, parentenv, handlers) #> env: [frame 0x555f3b323408] #> #> [[33]] #> <frame 1> (0) #> expr: tryCatch(withCallingHandlers({ <...> #> env: [frame 0x555f3b31fd10] #> #> [[34]] #> <frame 0> [global] #> expr: NULL #> env: [global] #> #> attr(,"class") #> [1] "ctxt_stack" "stack"
# It is especially useful when used within a function that needs to # inspect the evaluation stack but should nonetheless be callable # within nested calls without side effects: stack_util <- function() { # n = 2 means that two layers of intervening calls should be # removed: The layer at ctxt_stack()'s call site (including the # stack_trim() call), and the layer at stack_util()'s call. stack <- stack_trim(ctxt_stack(), n = 2) stack } user_fn <- function() { # A user calls your stack utility with intervening frames: identity(identity(stack_util())) } # These intervening frames won't appear in the evaluation stack identity(user_fn())
#> [[1]] #> <frame 35> (33) #> expr: user_fn() #> env: [local 0x555f3dcc19d0] #> #> [[2]] #> <frame 34> (33) #> expr: identity(user_fn()) #> env: [local 0x555f3dcc1960] #> #> [[3]] #> <frame 33> (32) #> expr: eval(expr, envir, enclos) #> env: [local 0x555f46b156c0] #> #> [[4]] #> <frame 32> (22) #> expr: eval(expr, envir, enclos) #> env: [local 0x555f3dcc17a0] #> #> [[5]] #> <frame 31> (22) #> expr: withVisible(eval(expr, envir, enclos)) #> env: [local 0x555f3dcd2140] #> #> [[6]] #> <frame 30> (22) #> expr: withCallingHandlers(withVisible(eval(expr, envir, enclos)), warning = wHandler, <...> #> env: [local 0x555f3dcd1ab0] #> #> [[7]] #> <frame 29> (28) #> expr: doTryCatch(return(expr), name, parentenv, handler) #> env: [local 0x555f3dcd1490] #> #> [[8]] #> <frame 28> (27) #> expr: tryCatchOne(expr, names, parentenv, handlers[[1L]]) #> env: [local 0x555f3dcd1148] #> #> [[9]] #> <frame 27> (26) #> expr: tryCatchList(expr, classes, parentenv, handlers) #> env: [local 0x555f3dcd0e00] #> #> [[10]] #> <frame 26> (25) #> expr: tryCatch(expr, error = function(e) { <...> #> env: [local 0x555f3dcd0738] #> #> [[11]] #> <frame 25> (24) #> expr: try(f, silent = TRUE) #> env: [local 0x555f3dcd0508] #> #> [[12]] #> <frame 24> (22) #> expr: handle(ev <- withCallingHandlers(withVisible(eval(expr, envir, <...> #> env: [local 0x555f3dcd0380] #> #> [[13]] #> <frame 23> (22) #> expr: timing_fn(handle(ev <- withCallingHandlers(withVisible(eval(expr, <...> #> env: [local 0x555f3dcea130] #> #> [[14]] #> <frame 22> (21) #> expr: evaluate_call(expr, parsed$src[[i]], envir = envir, enclos = enclos, <...> #> env: [frame 0x555f3e12cd40] #> #> [[15]] #> <frame 21> (20) #> expr: evaluate::evaluate(x, child_env(env), new_device = TRUE) #> env: [frame 0x555f405102a8] #> #> [[16]] #> <frame 20> (19) #> expr: highlight_examples(code, topic, env = env) #> env: [frame 0x555f40508698] #> #> [[17]] #> <frame 19> (18) #> expr: run_examples(tags$tag_examples[[1]], env = new.env(parent = globalenv()), <...> #> env: [frame 0x555f410aa7d8] #> #> [[18]] #> <frame 18> (17) #> expr: data_reference_topic(topic, pkg, examples = examples, run_dont_run = run_dont_run) #> env: [frame 0x555f418249f8] #> #> [[19]] #> <frame 17> (16) #> expr: .f(.x[[i]], ...) #> env: [frame 0x555f434f8ab0] #> #> [[20]] #> <frame 16> (15) #> expr: purrr::map(topics, build_reference_topic, pkg = pkg, lazy = lazy, <...> #> env: [frame 0x555f3cc9b7f8] #> #> [[21]] #> <frame 15> (14) #> expr: build_reference(pkg, lazy = lazy, examples = examples, run_dont_run = run_dont_run, <...> #> env: [frame 0x555f3ad79698] #> #> [[22]] #> <frame 14> (13) #> expr: build_site_local(pkg = pkg, examples = examples, run_dont_run = run_dont_run, <...> #> env: [frame 0x555f397076c8] #> #> [[23]] #> <frame 13> (12) #> expr: pkgdown::build_site(...) #> env: [frame 0x555f39c40618] #> #> [[24]] #> <frame 12> (0) #> expr: (function (..., crayon_enabled, crayon_colors, pkgdown_internet) <...> #> env: [frame 0x555f39c95938] #> #> [[25]] #> <frame 11> (0) #> expr: (function (what, args, quote = FALSE, envir = parent.frame()) <...> #> env: [frame 0x555f39c94828] #> #> [[26]] #> <frame 10> (0) #> expr: do.call(do.call, c(readRDS("/tmp/RtmpivJ8hr/callr-fun-1c30651e92ec"), <...> #> env: [frame 0x555f3b324c98] #> #> [[27]] #> <frame 9> (0) #> expr: saveRDS(do.call(do.call, c(readRDS("/tmp/RtmpivJ8hr/callr-fun-1c30651e92ec"), <...> #> env: [frame 0x555f3b325018] #> #> [[28]] #> <frame 8> (0) #> expr: withCallingHandlers({ <...> #> env: [frame 0x555f3b321a38] #> #> [[29]] #> <frame 7> (6) #> expr: doTryCatch(return(expr), name, parentenv, handler) #> env: [frame 0x555f3b3220c8] #> #> [[30]] #> <frame 6> (5) #> expr: tryCatchOne(expr, names, parentenv, handlers[[1L]]) #> env: [frame 0x555f3b322410] #> #> [[31]] #> <frame 5> (2) #> expr: tryCatchList(expr, names[-nh], parentenv, handlers[-nh]) #> env: [frame 0x555f3b3227c8] #> #> [[32]] #> <frame 4> (3) #> expr: doTryCatch(return(expr), name, parentenv, handler) #> env: [frame 0x555f3b322d78] #> #> [[33]] #> <frame 3> (2) #> expr: tryCatchOne(tryCatchList(expr, names[-nh], parentenv, handlers[-nh]), <...> #> env: [frame 0x555f3b3230c0] #> #> [[34]] #> <frame 2> (1) #> expr: tryCatchList(expr, classes, parentenv, handlers) #> env: [frame 0x555f3b323408] #> #> [[35]] #> <frame 1> (0) #> expr: tryCatch(withCallingHandlers({ <...> #> env: [frame 0x555f3b31fd10] #> #> [[36]] #> <frame 0> [global] #> expr: NULL #> env: [global] #> #> attr(,"class") #> [1] "ctxt_stack" "stack"