Можно ли создать функцию с состоянием с одним вызовом в R?
Я знаю, что могу создать функцию с состоянием 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)
- Почему adder2 не ассоциируется со средой своего анонимного родителя?
- Если adder2 живет в глобальной среде, почему он возвращает 1 (вместо
Error: object 'x' not found
при попытке оценить RHS внутреннего назначения,x+1
)? - Существуют ли другие умные способы создания функции, которая ведет себя как adder1, не назначая переменную для родительской функции?
1 ответ
Относительно 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