I have encountered a snippet of code where call contains another call. For example:
a <- 1
b <- 2
# First call
foo <- quote(a + a)
# Second call (call c
I think you might want :
eval(do.call(substitute, list(bar, list(foo = foo))))
# [1] 4
The call before evaluation :
do.call(substitute, list(bar, list(foo = foo)))
#(a + a)^b
This also works and might be easier to understand:
eval(eval(substitute(
substitute(bar, list(foo=foo)),
list(bar = bar))))
# [1] 4
and going backwards :
eval(substitute(
substitute(bar, list(foo=foo)),
list(bar = bar)))
# (a + a)^b
And some more
substitute(
substitute(bar, list(foo=foo)),
list(bar = bar))
# substitute(foo^b, list(foo = foo))
Not completely the same but you could use bquote
here too if you can afford to define bar
differently :
bar2 <- bquote(.(foo)^b)
bar2
# (a + a)^b
eval(bar2)
# [1] 4
And in that case the close equivalent using rlang
will be :
library(rlang)
foo <- expr(a + a) # same as quote(a + a)
bar2 <- expr((!!foo) ^ b)
bar2
# (a + a)^b
eval(bar2)
# [1] 4
And a minor thing, you say :
This is expected as R tries to run "foo" ^ 2
It doesn't, it tries to run quote(foo)^b
, which will return this same error if you run it directly in the console.
Addendum on recursion
Borrowing Oliver's example you can deal with recursion by looping on my solution until you've evaluated all you can, we just have to slightly modifiy our substitute
call to provide all the environment and not explicit substitutions :
a <- 1
b <- 2
c <- 3
foo <- quote(a + a)
bar <- quote(foo ^ b)
zz <- quote(bar + c)
fun <- function(x){
while(x != (
x <- do.call(substitute, list(x, as.list(parent.frame())))
)){}
eval.parent(x)
}
fun(bar)
# [1] 4
fun(zz)
# [1] 7
fun(foo)
# [1] 2