I am having a hard time understanding why my attempt to recursively apply eval
, using rapply
, is not working.
我很难理解为什么我使用rapply以递归方式应用eval的尝试不起作用。
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
.
很明显,递归有效,但它没有像我指定的那样评估全局环境中的表达式。基于这个答案,我将列表弄平了,并且可以使用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.)
据我所知,rapply / lapply在自己的环境中进行评估,就像任何其他函数一样,然后返回一个值。有意义的是,我可以指定全局环境或父框架(因为lapply的父框架应该是它所调用的环境 - 这里是全局环境。)
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
.
按照这个逻辑,我希望用rapply来指定全局环境。指定父框架应该失败(并且确实如此),因为我假设嵌套在rapply中的一个深度调用在由原始调用rapply创建的环境中进行评估。
What am I missing here? Why doesn't the rapply
call change x
in the global environment?
我在这里想念的是什么?为什么rapply调用不会在全球环境中改变x?
1 个解决方案
#1
7
Note from documentation for rapply
:
rapply文档中的注意事项:
The semantics differ in detail from lapply: in particular the arguments are evaluated before calling the C code.
语义与lapply的细节不同:特别是在调用C代码之前评估参数。
Try the following to see what they mean:
请尝试以下方法来查看它们的含义:
rapply(list(quote(stop("error"))), function(x) x)
# Error in (function (x) : error
lapply(list(quote(stop("error"))), function(x) x)
# [[1]]
# stop("error")
You can try this as a workaround:
你可以尝试这个解决方法:
rapply(exprs, evalq, envir = globalenv()) # updated with Hadley's equivalent but cleaner version.
# [1] 10 5 8 24
x
# [1] 24
As you noted, x
is getting evaluated in the rapply
environment, which is why the result makes sense, but the actual eval
statement is not of your original expression, but of the result (i.e. in the first iteration, 10
gets evaluated in the global env, not x <- x + 9
). By using substitute
we're able to salvage the original expression.
正如您所指出的那样,x正在rapply环境中进行评估,这就是结果有意义的原因,但实际的eval语句不是原始表达式,而是结果(即在第一次迭代中,10在全局中进行评估) env,而不是x < - x + 9)。通过使用替代品,我们能够挽救原始表达。
#1
7
Note from documentation for rapply
:
rapply文档中的注意事项:
The semantics differ in detail from lapply: in particular the arguments are evaluated before calling the C code.
语义与lapply的细节不同:特别是在调用C代码之前评估参数。
Try the following to see what they mean:
请尝试以下方法来查看它们的含义:
rapply(list(quote(stop("error"))), function(x) x)
# Error in (function (x) : error
lapply(list(quote(stop("error"))), function(x) x)
# [[1]]
# stop("error")
You can try this as a workaround:
你可以尝试这个解决方法:
rapply(exprs, evalq, envir = globalenv()) # updated with Hadley's equivalent but cleaner version.
# [1] 10 5 8 24
x
# [1] 24
As you noted, x
is getting evaluated in the rapply
environment, which is why the result makes sense, but the actual eval
statement is not of your original expression, but of the result (i.e. in the first iteration, 10
gets evaluated in the global env, not x <- x + 9
). By using substitute
we're able to salvage the original expression.
正如您所指出的那样,x正在rapply环境中进行评估,这就是结果有意义的原因,但实际的eval语句不是原始表达式,而是结果(即在第一次迭代中,10在全局中进行评估) env,而不是x < - x + 9)。通过使用替代品,我们能够挽救原始表达。