I am having a hard time understanding why my attempt to recursively apply eval
, using rapply
, is not working.
I have a nested list of expressions:
# Some expressions
expr1 <- quote(x <- x + 9)
expr2 <- quote(x <- x/2)
expr3 <- quote(x <- x + 3)
expr4 <- quote(x <- x * 3)
# Generate a nested list of expressions
exprs <- list(expr1, list(expr2, expr3), expr4)
# Initialize x, and attempt to eval the expressions
x <- 1
rapply(exprs, eval, envir = globalenv())
# Returns: [1] 10 5 8 24, but x is not changed.
Clearly the recursion worked, but it did not evaluate the expression in the global environment, like I specified. Based on this answer I flattened out the list, and can eval
using lapply
.
flatten <- function(x) {
repeat {
if(!any(vapply(x, is.list, logical(1)))) return(x)
x <- Reduce(c, x)
}
}
# Both change x to 24 in the global env, like desired.
lapply(flatten(exprs), eval, envir = globalenv())
lapply(flatten(exprs), eval, envir = parent.frame())
As far as I understand rapply
/lapply
evaluate in their own environment, just like any other function, then return a value. It makes sense that I can specify the global environment, or the parent frame (because the parent frame of lapply
should be the environment it was called in - here the global environment.)
Following this logic I would expect specifying the global environment with rapply
to work. Specifying the parent frame should fail (and it does), because I am assuming the calls nested one deep within rapply
get evaluated in the environment created by the original call to rapply
.
What am I missing here? Why doesn't the rapply
call change x
in the global environment?