eval:为什么 enclos = parent.frame() 会有所不同?

eval: why does enclos = parent.frame() make a difference?

中,以下抛出错误:

subset2 = function(df, condition) {
  condition_call = eval(substitute(condition),df )  
  df[condition_call,]
}

df = data.frame(a = 1:10, b = 2:11)
condition = 3

subset2(df, a < condition)
## Error in eval(substitute(condition), df) : object 'a' not found

最初问题中的 Josh 和 Jason 很好地解释了这是为什么。我不明白的是为什么向 eval 提供 enclos 参数显然可以修复它。

subset3 = function(df, condition) {
  condition_call = eval(substitute(condition), envir = df, enclos = parent.frame())
  df[condition_call, ]
}

subset3(df, a < condition)
##   a b
## 1 1 2
## 2 2 3

我知道跳过函数环境意味着 R 不再尝试评估承诺,而是从全局环境中获取条件对象。

但我认为提供 enclos = parent.frame() 应该不会有什么不同。来自 ?eval 的 enclos 参数:

Specifies the enclosure, i.e., where R looks for objects not found in envir.

但如果不提供,则默认为:

enclos = if(is.list(envir) || is.pairlist(envir)) parent.frame() else baseenv())

在我看来,无论如何应该解析为 parent.frame(),因为 df 肯定满足 is.list() 检查。

这意味着只要某些对象 data returns 在 is.list() 上为 TRUE,eval(expr, envir = data)eval(expr, envir = data, enclos = parent.frame()) 的行为应该是相同的。但正如上面所证明的那样,事实并非如此。

我错过了什么?

编辑: 感谢 SmokeyShakers,他们指出了关于评估时间的默认参数和用户提供的参数之间的区别。我认为这实际上已经在这里表达了:

不过,让这个问题继续存在可能是有意义的,因为它具体涉及 eval()(另一个没有),并且在得到答案之前意识到普遍的问题应该是什么并非易事.

所以,不同parents。在不起作用的示例中,parent.frameeval 内部向上查找 subset2 的内部环境。在工作示例中,parent.framesubset3 内部向上看,很可能是你的 df 所在的全局。

示例:

tester <- function() {
  print(parent.frame())
} 

tester() # Global

(function() {
  tester()
})() # Anonymous function's internal env

IT 对 condition 的双重使用感到困惑。将其中之一更改为 cond:

cond <- 3
subset2(df, a < cond)
##   a b
## 1 1 2
## 2 2 3

请注意,即使这行得通,但如果将 subset2 放入函数中,它将不起作用,因为它会查看定义了 subset2 的全局环境,而不是查看 [=需要 16=] 执行框架和 subset3

if (exists("cond")) rm(cond)
f <- function() {
  cond <- 3
  subset2(df, a < cond)
}
f() # error