The function base::substitute(expr, env)
, as per its documentation page,
returns the parse tree for the (unevaluated) expression expr, substituting any variables bound in env.
I am looking for a way of substituting any variables bound not in one specific environment, but in all environments in the current call stack, i.e. all environments encountered by iterating over parent.frame(i)
where i
is in seq_len(sys.nframe())
. Additionally, I'd like standard scoping rules to apply.
This is a contradiction: standard scoping in R is lexical, but what I describe here is dynamic scoping (thank you @MikkoMarttila for helping me clear this up). What I actually want is a way of substituting any variables bound not in one specific environment, but in all parent enclosing environments, the set of which can be enumerated by repeatedly applying base::parent.env()
.
Consider the following example:
do_something <- function(todo) {
cat(
paste(
deparse(substitute(todo, environment())),
collapse = "\n"
)
)
}
nested_do <- function() {
var_2 <- "goodbye"
do_something({
print(var_1)
print("world")
print(var_2)
})
}
var_1 <- "hello"
nested_do()
Currently this gives
print(var_1)
print("world")
print(var_2)
where I'd like to have
print("hello")
print("world")
print("goodbye")
I have looked at base::bquote()
and rlang::enexpr()
but for both I have to explicitly mark the variables for substitution/unquoting with .()
or !!
. I'd rather not have to specify variables manually, but have everything resolved that is found (just like in base::substitute()
). Furthermore, I tried iteratively applying base::substitute()
with the respective env
arguments and I had a look at oshka::expand()
, but nothing I tried, does what I need.
Any help is much appreciated.
Additional context
What I'm trying to achieve is the following: I'm working on a cluster running LSF. This means that I can submit jobs using the submission tool bsub
which may take an R file as input. Now I would like to have a script that generates these input files (e.g. using the function do_something()
).
long_running_fun <- function(x) {
Sys.sleep(100)
x / 2
}
var_1 <- 2 + 2
var_2 <- var_1 + 10
do_something({
print(var_1)
var_3 <- long_running_fun(var_2)
print(var_3)
})
I in the above case, want the following (or something equivalent) to be written to a file
print(4)
var_3 <- long_running_fun(14)
print(var_3)