R中的动态范围问题

Jas*_*son 5 eval r dynamic-scope

我正在阅读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)
Run Code Online (Sandbox Code Playgroud)

然后我收到以下错误消息:

eval中的错误(替换(条件),df):找不到对象'a'

我阅读的解释如下,但不太明白:

如果eval()无法在数据框(第二个参数)中找到变量,则它会查找subset2()的环境.这显然不是我们想要的,所以我们需要一些方法告诉eval()在哪里查看它是否找不到数据框中的变量.

在我看来,虽然"eval(替代(条件),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)
Run Code Online (Sandbox Code Playgroud)

Jos*_*ien 3

这个更精简的示例可能会让您更轻松地了解 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
Run Code Online (Sandbox Code Playgroud)

另一件需要理解的重要事情是,在调用函数的计算框架中搜索提供的参数中的符号(此处为condition = condition + aat的右侧部分)。#4来自第 4.3.3 节R 语言定义的参数评估:

关于函数参数求值需要了解的最重要的事情之一是提供的参数和默认参数的处理方式不同。为函数提供的参数在调用函数的求值框架中求值。函数的默认参数在函数的求值框架中求值。

在上面的示例中,调用的评估框架f()是全局环境.GlobalEnv

逐步执行此操作,当您致电 时会发生以下情况(condition = condition + a)。在函数求值期间,R 遇到condition + a函数体中的表达式 (at #2)。它搜索a和的值condition,并找到本地分配的符号a。它发现该符号condition绑定到名为condition(at #1) 的形式参数。在函数调用期间提供的形式参数的值是( at condition + a) #4

如 R 语言定义中所述,表达式中符号的值condition + a是在调用函数的环境(此处为全局环境)中搜索的。由于全局环境包含一个名为condition(在 处分配#3)的变量,但没有名为 的变量a,因此它无法计算表达式condition + a(at #4),并且失败并出现您看到的错误。