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.frame
从 eval
内部向上查找 subset2
的内部环境。在工作示例中,parent.frame
从 subset3
内部向上看,很可能是你的 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
在
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.frame
从 eval
内部向上查找 subset2
的内部环境。在工作示例中,parent.frame
从 subset3
内部向上看,很可能是你的 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