评估:为什么enclos = parent.frame()有所作为? [英] eval: why does enclos = parent.frame() make a difference?

查看:63
本文介绍了评估:为什么enclos = parent.frame()有所作为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题中,以下内容引发错误:

In this question, the following throws an error:

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参数显然可以解决这个问题.

Josh and Jason from the original question did a great job explaining why this is. What I don't get is why supplying the enclos argument to eval apparently fixes it.

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不再试图评估Promise,而是从全局环境中获取条件对象.

I understand that skipping the function environment means R is no longer trying to evaluate the promise, and instead grabs the condition object from the global environment.

但是我认为提供enclos = parent.frame()应该没有什么不同.从?eval的enclos参数开始:

But I think supplying enclos = parent.frame() should not make a difference. From ?eval on the enclos argument:

指定机箱,即R在其中查找在环境中找不到的对象.

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

但是,如果未提供,则默认为:

But if not provided, it defaults to:

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

在我看来,

无论如何应该解析为parent.frame(),因为df当然可以满足is.list()的检查要求.

which, in my mind, should resolve to parent.frame() anyway, because surely, df satisfies the is.list() check.

这意味着,只要某些对象datais.list()上返回TRUE,eval(expr, envir = data)eval(expr, envir = data, enclos = parent.frame())的行为就应该相同.但如上所述,事实并非如此.

This means that as long as some object data returns TRUE on is.list(), the behavior of eval(expr, envir = data) and eval(expr, envir = data, enclos = parent.frame()) should be identical. But as evidenced by the above, it isn't.

我想念什么?

编辑:感谢SmokeyShakers指出了评估时间的默认参数和用户提供的参数之间的区别.我认为这实际上已经在这里表达了: https://stackoverflow.com/a/15505111/2416535

Thanks to SmokeyShakers who pointed out the difference between default and user-supplied arguments regarding the time of evaluation. I think this is actually already expressed here: https://stackoverflow.com/a/15505111/2416535

尽管可以使这个问题存活下来,这很有意义,因为它特别触及了eval()(另一个问题则没有),并且在一个问题得到答案之前,认识到广义问题应该是什么并不容易.

It might make sense to keep this one alive though, as it touches eval() specifically (the other does not), and it is not trivial to realize what the generalized question should be until one has the answer.

推荐答案

因此,父母不同.在不起作用的示例中,parent.frame是从eval内部查找到subset2的内部环境的.在工作示例中,parent.frame是从subset3内部查找的,很可能是df所在的全局位置.

So, different parents. In the example that doesn't work parent.frame is looking up from inside eval into the internal environment of subset2. In the working example, parent.frame is looking up from inside subset3, likely to your global where your df sits.

示例:

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

tester() # Global

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

这篇关于评估:为什么enclos = parent.frame()有所作为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆