R 中的函数环境

Function environment in R

我有下面的代码来理解复杂的环境层:

depositor <- function() {
  balance <- 0
  function(amount) {
   balance <<- balance + amount # assign in the parent
    return(balance) 
  } 
}
deposit <- depositor()
deposit(100)
100
deposit(32)
132

能否请您解释一下上述代码在环境方面的工作原理?

我没看懂deposit <- depositor()

谢谢大家!

理解这个例子的关键是depositor() 它将 return

depositor()

function(amount) {
   balance <<- balance + amount # assign in the parent
    return(balance) 
  }
<environment: 0x8936fb0>

这部分比较简单。外部函数 depositor() 内的最后一个完整块是匿名函数 function(amount) 的定义。所以正是这个函数变成了外部函数的 return 值,就像任何普通变量一样。 balance和这个匿名函数的作用域都限制在外层函数,即depositor,其中none可以直接从外部访问。

但是,这样 returned 的匿名函数可以在父框架(全局环境)中存储和重用。

 environment(fun = depositor)
# <environment: R_GlobalEnv>
 environment(fun = deposit)
# <environment: 0x8a3f5a8>
parent.env(  environment(fun = deposit) )
# <environment: R_GlobalEnv>

deposit <- depositor() 将这个重新调整的函数存储在一个名为 deposit 的 var 中,可以通过它访问它 deposit(amountvalue)

amount的范围还是限于内部函数。无法通过外部函数将 amount 的值传递给它,因为它没有分配给其他任何地方。这只能通过保存的代理完成 deposit(100)


编辑:我重新审视了我的答案,发现我遗漏了这个练习中最有趣的部分。为什么 balance 的值在一次调用中持续存在?即,为什么下一次调用不将 balance 的值重置为 0? 每次对 depositor()not deposit!)的新调用都将 return 一个具有自己的 parent/enclosing 环境的函数。这是@Kota Mori 在上面的评论中也建议的proof:It:

deposit<- depositor()
x<- depositor()

#following will have two different values
environment(deposit)
environment(x) 
# and they will work independently
x(100); x(20)
deposit(100);deposit(1000)

这是 closure 的关键,我对这个话题几乎没有什么可说的。调用内部函数 i.e., x() or deposit() 不会干扰与先前调用关联的环境,因为不会调用父函数本身,只会调用内部函数。在这种情况下,内部函数还通过 <<- 赋值更新其各自封闭环境中的余额,从而将一次调用的值保存到 next


另一件事可能是,为什么从函数 returned 的变量没有类似的外壳?这是因为根据 function 的文档 - the value of the last evaluated expression is returned.