3

I recently ran into some unexpected R behavior, which can be reproduced in its simplest form with the following code:

make.adder <- function(a) {function(x) {x + a}}
s <- list(1, 2)
adders <- lapply(s, make.adder)

We might now expect adders[[1]] to be a function which adds 1, and adders[[2]] to be a function which adds 2. However,

adders[[1]](1)

returns 3 (when we might've expected 2). Taking a look at the environment with

environment(adders[[1]])$a

returns 2, which is again surprising (but consistent). What's going on here?

We see similar behavior if we try to instead use a for loop:

adders <- list()
for (i in seq(1, 2)) {adders[[i]] <- make.adder(i)}

Again, adders[[1]] (1) returns 3. How can we create a list of 100 functions, such that the i'th function is make.adder(i)?

1 Answers1

2

I think you need to use force() to make sure the parameter is evaluated when you expect it to be. See ?force for more information ...

make.adder <- function(a) { force(a); function(x) {x + a}}
s <- list(1, 2)
adders <- lapply(s, make.adder)

adders[[1]](1) ## 2
Ben Bolker
  • 211,554
  • 25
  • 370
  • 453