3

所以在 Hadley 的高级 R 书中,有一个使用替代的问题示例,这里是代码的摘录:

subset2 <- function(x, condition) {
condition_call <- substitute(condition)
r <- eval(condition_call, x, parent.frame())
x[r, ]
}

scramble <- function(x) x[sample(nrow(x)), ]

subscramble <- function(x, condition) {
 scramble(subset2(x, condition))
}


subscramble(sample_df, a >= 4)
# Error in eval(expr, envir, enclos) : object 'a' not found
traceback()
#> 5: eval(expr, envir, enclos)
#> 4: eval(condition_call, x, parent.frame()) at #3
#> 3: subset2(x, condition) at #1
#> 2: scramble(subset2(x, condition)) at #2
#> 1: subscramble(sample_df, a >= 4)

你能看出问题所在吗?condition_call 包含表达式条件。因此,当我们评估 condition_call 时,它也会评估 condition,它的值 a >= 4。但是,这无法计算,因为在父环境中没有名为 a 的对象。但是,如果在全局环境中设置了 a,则可能会发生更令人困惑的事情:

在本书的上述段落中,有几件事让我感到困惑。

  1. 句子“condition_call 包含表达式条件”。符号“条件”在函数子集 2 中用作形式参数,也用于 scramble(subset2(x,condition)) 中的实参数。我猜他提到了这个真实/调用参数“条件”,对吗?

  2. 作为一个承诺,subscramble 定义中的条件是惰性求值的?为什么调用时不评估它:scramble(subset2(x,condition))

换句话说,我如何通过查看代码来知道一个 Promise 是否被评估?例如,如果我理解正确,如果我将代码更改为以下内容:

scramble(subset2(x,(condition))) 

现在条件被强制评估。这里有什么规则?

  1. 当 Hadley 说“当我们评估 condition_call 时,它也会评估 condition”,“它”是什么?他的意思是“评估”触发了某种内部或二次评估,试图解决承诺“条件”吗?这发生在哪里?即R试图使用什么环境来找出“条件”的值是什么?

  2. 所以错误“object a not found”不是由于下面调用中的“x”或“parent.frame()”,而是在其他地方?我完全糊涂了。

    r <- eval(condition_call, x, parent.frame())

4

1 回答 1

3

我无法发表评论,所以我会发布这个作为答案。一切都将只是重新散列:

R中另一个函数的非标准评估

基本上发生的事情是在 sample_df 调用环境中,该函数将寻找“条件”而不是“a> = 4”。由于找不到它,它向上移动,然后在调用环境中找到条件;subscramble 执行环境(这是因为 subset2(x, condition) 是在此环境中创建的一个 Promise),它发现 a>=4。

现在它需要找到 a,但我们已经离开了 sample_df 数据环境,所以它在全局环境中搜索它,如果在全局环境中定义了 a,则会导致奇怪的结果。

于 2015-07-23T11:00:53.040 回答