R 中的动态范围问题
Dynamic scoping questions in R
我正在阅读 Hadley 的 AdvancedR 并在此 URL
上测试以下代码
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
看了下面的解释还是不太明白:
If eval() can’t find the variable inside the data frame (its second argument), it looks in the environment of subset2(). That’s obviously not what we want, so we need some way to tell eval() where to look if it can’t find the variables in the data frame.
在我看来,虽然"eval(substitute(condition),df )",他们找不到的变量是条件,那为什么找不到对象"a"?
另一方面,为什么下面的代码不会出错?
subset2 = function(df, condition){
condition_call = eval(substitute(condition),df )
df[condition_call,]
}
df = data.frame(a = 1:10, b = 2:11)
y = 3
subset2(df, a < y)
这个更精简的示例可能会让您更容易了解 Hadley 示例中发生的事情。首先要注意的是,符号 condition
在这里以四个不同的角色出现,每个角色我都用编号注释进行了标记。
## Role of symbol `condition`
f <- function(condition) { #1 -- formal argument
a <- 100
condition + a #2 -- symbol bound to formal argument
}
condition <- 3 #3 -- symbol in global environment
f(condition = condition + a) #4 -- supplied argument (on RHS)
## Error in f(condition = condition + a) (from #1) : object 'a' not found
另一件需要理解的重要事情是,在调用函数的评估框架中搜索提供的参数中的符号(此处 condition = condition + a
在 #4
的右侧部分)。来自 Section 4.3.3 Argument Evaluation 的 R 语言定义:
One of the most important things to know about the evaluation of arguments to a function is that supplied arguments and default arguments are treated differently. The supplied arguments to a function are evaluated in the evaluation frame of the calling function. The default arguments to a function are evaluated in the evaluation frame of the function.
在上面的例子中,调用f()
的评估框架是全局环境,.GlobalEnv
。
逐步进行,下面是调用 (condition = condition + a)
时发生的情况。在函数求值期间,R 在函数体中(在 #2
处)遇到了表达式 condition + a
。它搜索 a
和 condition
的值,并找到本地分配的符号 a
。它发现符号 condition
绑定到名为 condition
的形式参数(位于 #1
)。在函数调用期间提供的 that 形式参数的值为 condition + a
(在 #4
处)。
如 R 语言定义中所述,表达式 condition + a
中符号的值是在调用函数的环境中搜索的,这里是全局环境。由于全局环境包含一个名为 condition
的变量(在 #3
处分配)但没有名为 a
的变量,因此无法计算表达式 condition + a
(在 #4
), 并失败并出现您看到的错误。
我想添加一些细节以防有人偶然发现这个问题。有问题的行是
condition_call = eval(substitute(condition),df )
substitute()函数中的condition对象是promise对象,其表达式槽为"a < condition",substitute(condition)取表达式和returns 表达式为 "a < condition".
的调用对象
然后 eval() 函数开始计算 df 环境中的 "a < condition"。它的目标是找到 a 和 condition.
- a 在 df 中成功找到,而这不是产生错误的地方。
- 然后R开始在df中搜索condition,找不到。
- 于是R上去了subset2的执行环境,在执行环境中查找条件。
- 它找到的变量其实就是之前提到的表达式槽为"a < condition".
的promise对象
- 要计算这个表达式,R 必须再次找到 a,现在它找不到了,因为它已经通过了 df 环境。 这是真正产生错误的部分。
总结一下这里的问题:
- R 确实在 df 中找到 a 一次。
- 当 R 尝试寻找 condition 然后 R 获取 promise 对象 condition 而不是 4 在外部分配作为参数并尝试对其求值。
- 然后R遇到问题:
- 它尝试计算 "a < condition",但在 subset2() 的执行环境或全局环境中找不到 a。
对于我的第二个例子,R 在执行环境中找不到 y,然后在 subset2() 的调用环境中找到 y 为 4,没有产生错误。在这种情况下,y 的名称与 promise 对象 condition 不同,R 不会尝试计算 "a < y" 并且不会生成错误。
我正在阅读 Hadley 的 AdvancedR 并在此 URL
上测试以下代码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
看了下面的解释还是不太明白:
If eval() can’t find the variable inside the data frame (its second argument), it looks in the environment of subset2(). That’s obviously not what we want, so we need some way to tell eval() where to look if it can’t find the variables in the data frame.
在我看来,虽然"eval(substitute(condition),df )",他们找不到的变量是条件,那为什么找不到对象"a"?
另一方面,为什么下面的代码不会出错?
subset2 = function(df, condition){
condition_call = eval(substitute(condition),df )
df[condition_call,]
}
df = data.frame(a = 1:10, b = 2:11)
y = 3
subset2(df, a < y)
这个更精简的示例可能会让您更容易了解 Hadley 示例中发生的事情。首先要注意的是,符号 condition
在这里以四个不同的角色出现,每个角色我都用编号注释进行了标记。
## Role of symbol `condition`
f <- function(condition) { #1 -- formal argument
a <- 100
condition + a #2 -- symbol bound to formal argument
}
condition <- 3 #3 -- symbol in global environment
f(condition = condition + a) #4 -- supplied argument (on RHS)
## Error in f(condition = condition + a) (from #1) : object 'a' not found
另一件需要理解的重要事情是,在调用函数的评估框架中搜索提供的参数中的符号(此处 condition = condition + a
在 #4
的右侧部分)。来自 Section 4.3.3 Argument Evaluation 的 R 语言定义:
One of the most important things to know about the evaluation of arguments to a function is that supplied arguments and default arguments are treated differently. The supplied arguments to a function are evaluated in the evaluation frame of the calling function. The default arguments to a function are evaluated in the evaluation frame of the function.
在上面的例子中,调用f()
的评估框架是全局环境,.GlobalEnv
。
逐步进行,下面是调用 (condition = condition + a)
时发生的情况。在函数求值期间,R 在函数体中(在 #2
处)遇到了表达式 condition + a
。它搜索 a
和 condition
的值,并找到本地分配的符号 a
。它发现符号 condition
绑定到名为 condition
的形式参数(位于 #1
)。在函数调用期间提供的 that 形式参数的值为 condition + a
(在 #4
处)。
如 R 语言定义中所述,表达式 condition + a
中符号的值是在调用函数的环境中搜索的,这里是全局环境。由于全局环境包含一个名为 condition
的变量(在 #3
处分配)但没有名为 a
的变量,因此无法计算表达式 condition + a
(在 #4
), 并失败并出现您看到的错误。
我想添加一些细节以防有人偶然发现这个问题。有问题的行是
condition_call = eval(substitute(condition),df )
substitute()函数中的condition对象是promise对象,其表达式槽为"a < condition",substitute(condition)取表达式和returns 表达式为 "a < condition".
的调用对象
然后 eval() 函数开始计算 df 环境中的 "a < condition"。它的目标是找到 a 和 condition.
- a 在 df 中成功找到,而这不是产生错误的地方。
- 然后R开始在df中搜索condition,找不到。
- 于是R上去了subset2的执行环境,在执行环境中查找条件。
- 它找到的变量其实就是之前提到的表达式槽为"a < condition". 的promise对象
- 要计算这个表达式,R 必须再次找到 a,现在它找不到了,因为它已经通过了 df 环境。 这是真正产生错误的部分。
总结一下这里的问题:
- R 确实在 df 中找到 a 一次。
- 当 R 尝试寻找 condition 然后 R 获取 promise 对象 condition 而不是 4 在外部分配作为参数并尝试对其求值。
- 然后R遇到问题:
- 它尝试计算 "a < condition",但在 subset2() 的执行环境或全局环境中找不到 a。
对于我的第二个例子,R 在执行环境中找不到 y,然后在 subset2() 的调用环境中找到 y 为 4,没有产生错误。在这种情况下,y 的名称与 promise 对象 condition 不同,R 不会尝试计算 "a < y" 并且不会生成错误。