环境如何记住它的存在?

How does an environment remember that it exists?

adder <- local({
x <- 0
function() {x <<- x+1; x}
})

或等同于

adderGen <- function(){
x <- 0
function() {x <<- x+1; x}
}
adder<-adderGen()

调用 adder() 将 return 1 再次调用它 returns 2,依此类推。但是 adder 是如何计算的呢?我看不到任何影响全局环境的变量,那么实际用来存储这些变量的是什么?特别是在第二种情况下,您希望 adder 忘记它是在函数调用内部进行的。

每个函数都保留将其定义为函数一部分的环境。如果 f 是一个函数,那么 environment(f) 显示它。通常 adderGen 中的执行环境在退出时会被丢弃,但是因为 adderGen 传递出一个函数,其环境是 adderGen 中的执行环境,该环境作为函数的一部分保留晕倒。我们可以通过显示adderGen中的执行环境来验证,然后验证它是否与adder中的环境相同。 trace函数会在adderGen函数体的开头插入打印语句,每次adderGen运行时都会显示执行环境。 environment(adder)是同样的环境。

trace(adderGen, quote(print(environment())))
## [1] "adderGen"

adder <- adderGen()
## Tracing adderGen() on entry 
## <environment: 0x0000000014e77780>

environment(adder)
## <environment: 0x0000000014e77780>   

为了看看发生了什么,让我们定义函数如下:

adderGen <- function(){
  print("Initialize")
  x <- 0
  function() {x <<- x+1; x}
}

当我们评估它时,我们得到:

adder <- adderGen()
# [1] "Initialize"

赋值给adder的对象是adderGen的内部函数(即adderGen的输出)。请注意,adder 不再打印 "Initialize"

adderGen
# function(){
#   print("Initialize")
#   x <- 0
#   a <- function() {x <<- x+1; x}
# }
adder
# function() {x <<- x+1; x}
# <environment: 0x55cd4ebd3390>

我们可以看到它也创建了一个新的调用环境,它继承了adderGen.

环境中的变量x
ls(environment(adder))
# [1] "x"
get("x",environment(adder))
# [1] 0

第一次执行adder时,它使用x的继承值,即0,将x重新定义为全局变量(在其调用环境中)。而这个全局变量就是它在下一次执行中使用的那个。因为 x <-0 不是函数 adder 的一部分,所以当 adder 被执行时,变量 x 没有被初始化为 0 并且它将 [= 的当前值递增 1 20=].

adder()
# [1] 1