3

我知道我可以adder使用以下工厂函数创建有状态函数adder_maker

adder_maker <- function() {x <- 0; function() {x <<- x+1; x}}
adder1 <- adder_maker()
adder1()
adder1()
environment(adder1)

该函数按预期递增并位于其自己的封闭环境中。

但是,如果我不想将工厂函数存储在中间变量中,那么内部函数最终会出现在全局环境中。

adder2 <- function() {x <- 0; function() {x <<- x+1; x}}()
adder2()
adder2()
environment(adder2)
  1. 为什么 adder2 不与其匿名父级的环境相关联?
  2. 如果 adder2 存在于全局环境中,为什么它会返回 1(而不是Error: object 'x' not found,在尝试评估内部分配的 RHS 时,x+1)?
  3. 有没有其他聪明的方法来创建一个行为类似于 adder1 的函数,而不为父函数分配一个变量?
4

1 回答 1

2

关于1和2):

这与评估的顺序有关。你的代码是:

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

这里首先执行的是 R 表达式{x <- 0; function() {x <<- x+1; x}}。您可能知道 R 中表达式的值是表达式中的最后一个值。所以在这种情况下,表达式计算为一个匿名函数(它存在x <- 0于定义的环境中):

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

在下一步中,这个中间函数被调用(而不是你期望的整个事情!)这个中间代码的结果当然是 1。所以剩下的实际上是:

adder2 <- function() 1

如评论中所述,这解释了该行为,以及为什么它与括号一起使用。

关于3):

您正在寻找功能local

> adder2 <- local({x <- 0; function() {x <<- x+1; x}})
> adder2()
[1] 1
> adder2()
[1] 2
于 2018-08-30T14:19:52.787 回答