是否可以通过R中的一个调用来创建有状态函数?

时间:2018-08-30 04:12:09

标签: r function r-environment

我知道我可以按照以下说明使用工厂函数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的函数,而无需为父函数分配变量?

1 个答案:

答案 0 :(得分: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