apply family 函数的作用域是怎样的?

How are apply family functions scoped?

考虑:

x <- 5
replicate(10, x <- x + 1)

这有输出 c(6, 6, 6, 6, 6, 6, 6, 6, 6, 6)。然而:

x <- 5
replicate(10, x <<- x + 1)

有输出 c(6, 7, 8, 9, 10, 11, 12, 13, 14, 15).

这对 x <- x + 1 的评估环境意味着什么?我是否相信 x 被视为 replicate 的内部变量?这似乎是我所看到的,但是当我咨询 the relevant section of the language definition 时,我看到了以下内容:

It is also worth noting that the effect of foo(x <- y) if the argument is evaluated is to change the value of x in the calling environment and not in the evaluation environment of foo.

但是如果 x 真的在调用环境中发生了变化,那么为什么会这样:

x <- 5
replicate(10, x <- x + 1)
x

Return 5 而不是 15?我误解了哪一部分?

你从语言定义中引用的那句话是关于标准评估的,但是replicate使用non-standard评估。这是它的来源:

replicate <- function (n, expr, simplify = "array") 
sapply(integer(n), eval.parent(substitute(function(...) expr)), 
    simplify = simplify)

substitute(function(...) expr) 调用采用您的表达式 x <- x + 1 而不对其求值,并创建一个新函数

function(...) x <- x + 1

这是传递给 sapply() 的函数,它将它应用于长度为 n 的向量。所以所有的赋值都发生在那个匿名函数的框架中。

当你使用x <<- x + 1时,计算仍然发生在构造函数中,但它的环境是replicate()的调用环境(因为eval.parent调用),并且那就是分配发生的地方。这就是为什么您会在输出中获得递增的值。

所以我认为你对手册的理解是正确的,但它并没有明确说明它是在谈论标准评估的情况。以下段落暗示了这里发生的事情:

It is possible to access the actual (not default) expressions used as arguments inside the function. The mechanism is implemented via promises. When a function is being evaluated the actual expression used as an argument is stored in the promise together with a pointer to the environment the function was called from. When (if) the argument is evaluated the stored expression is evaluated in the environment that the function was called from. Since only a pointer to the environment is used any changes made to that environment will be in effect during this evaluation. The resulting value is then also stored in a separate spot in the promise. Subsequent evaluations retrieve this stored value (a second evaluation is not carried out). Access to the unevaluated expression is also available using substitute.

但是 replicate() 的帮助页面并没有说明它在做什么。

顺便说一句,您的标题询问有关应用族函数的问题:但是 replicate 以外的大多数都明确要求函数,因此不会出现此问题。例如,很明显这不会影响全局 [​​=23=]:

sapply(integer(10), function(i) x <- x + 1)