Можно ли создать функцию с состоянием с одним вызовом в R? - PullRequest
0 голосов
/ 30 августа 2018

Я знаю, что могу создать функцию с состоянием 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 голосов
/ 30 августа 2018

Относительно 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
...