Reputation: 1258
I know that I can create a stateful function adder
using the factory function adder_maker
per the below:
adder_maker <- function() {x <- 0; function() {x <<- x+1; x}}
adder1 <- adder_maker()
adder1()
adder1()
environment(adder1)
The function increments as expected and sits in its own enclosing environment.
However, if I don't want to store the factory function in an intermediate variable, then the inner function ends up in the global environment.
adder2 <- function() {x <- 0; function() {x <<- x+1; x}}()
adder2()
adder2()
environment(adder2)
Error: object 'x' not found
, when attempting to evaluate RHS of the inner assignment, x+1
)?Upvotes: 3
Views: 114
Reputation: 5650
Regarding 1 and 2):
This has to do with the order of evaluation. Your code was:
adder2 <- function() {x <- 0; function() {x <<- x+1; x}}()
What gets executed at first here is the R expression {x <- 0; function() {x <<- x+1; x}}
. You probably know that the value of an expression in R is the last value within the expression. So in this case, the expression evaluates to an anonymous function (which lives an environment where x <- 0
was defined):
> {x <- 0; function() {x <<- x+1; x}}
function() {x <<- x+1; x}
In the next step, this intermediate function gets called (and not the whole thing as you expected!) The result of this intermediate code is of course 1. So what remains is effectively is:
adder2 <- function() 1
This explains the behavior, and also why it works with parentheses, as noted in comments.
Regarding 3):
You are looking for the function local
:
> adder2 <- local({x <- 0; function() {x <<- x+1; x}})
> adder2()
[1] 1
> adder2()
[1] 2
Upvotes: 2