繁体   English   中英

全局环境中的递归eval

[英]Recursive eval in the global environment

我很难理解为什么我使用rapply以递归方式应用eval尝试不起作用。

我有一个嵌套的表达式列表:

# 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.

很明显,递归有效,但它没有像我指定的那样评估全局环境中的表达式。 基于这个答案我夷为平地的列表,并且可以eval使用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())

据我所知, rapply / lapply在自己的环境中进行评估,就像任何其他函数一样,然后返回一个值。 有意义的是,我可以指定全局环境或父框架(因为lapply的父框架应该是它所调用的环境 - 这里是全局环境。)

按照这个逻辑,我希望用rapply指定全局环境。 指定父框架应该失败(并且确实如此),因为我假设嵌套在rapply一个深度调用在由原始调用rapply创建的环境中进行评估。

我在这里错过了什么? 为什么rapply调用不会在全球环境中改变x

rapply文档中的注意事项:

语义与lapply的细节不同:特别是在调用C代码之前评估参数

请尝试以下方法来查看它们的含义:

rapply(list(quote(stop("error"))), function(x) x)
# Error in (function (x)  : error
lapply(list(quote(stop("error"))), function(x) x)
# [[1]]
# stop("error")

你可以尝试这个解决方法:

rapply(exprs, evalq, envir = globalenv())  # updated with Hadley's equivalent but cleaner version.
# [1] 10  5  8 24
x
# [1] 24

正如您所指出的, x正在rapply环境中进行评估,这就是结果有意义的原因,但实际的eval语句不是原始表达式,而是结果(即在第一次迭代中, 10在全局中进行评估) env,而不是x <- x + 9 )。 通过使用substitute我们能够挽救原始表达。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM