【问题标题】:Recursive eval in the global environment全局环境中的递归评估
【发布时间】:2014-04-28 19:52:12
【问题描述】:

我很难理解为什么我使用 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.

显然递归有效,但它没有像我指定的那样评估全局环境中的表达式。基于this answer,我将列表展平,可以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

【问题讨论】:

  • 请注意,您确实应该在这里使用quote(),而不是bquote()
  • @hadley 同意。在我的实际代码中,我有一个使用bquote() 生成data.table 表达式的函数列表,即。 bquote(dat[.(ids), dosomething]),我正在尝试找出评估表达式对象嵌套列表的最佳方法。我也看过你的as.quoted()

标签: r


【解决方案1】:

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 在全局环境中被评估,而不是x &lt;- x + 9)。通过使用substitute,我们可以挽救原来的表达方式。

【讨论】:

  • rapply(exprs, evalq, envir = globalenv())
  • 在这种情况下,还不清楚评估的含义。我怀疑rapply() 的行为是一个错误
  • @hadley & BrodieG,如果您有兴趣,这个解决方案不再适用于 R-3.2。我问了一个后续问题:stackoverflow.com/q/31416347/1623354.
猜你喜欢
  • 2020-07-12
  • 2013-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-05
  • 2021-08-28
  • 2011-04-01
相关资源
最近更新 更多