Search code examples
rscoping

Scoping problem when assigning functions in a loop


I would like to create a bunch of functions with a particular structure in the variable name as a crude workaround for what should be one function with multiple arguments (this I cannot do directly). Let's consider the following analogous example:

for(i in 1:3){
  for(j in 1:2){
    temp_fun <- function(x){
      (x+i)^j
      }
    assign(paste0("fun", paste0("_plus_", i, "_pow_", j)), temp_fun)
  }
}

This loop creates 6 functions that have x as dependent variable only

fun_plus_1_pow_1
fun_plus_1_pow_2
fun_plus_2_pow_1
fun_plus_2_pow_2
fun_plus_3_pow_1
fun_plus_3_pow_2

For instance fun_plus_2_pow_1(2) should return (2+2)^1 = 4, however it returns 25. I know what happens here, the values for i and j get updated while the loop is running and eventually i=3 and j=2are taken resulting in (2+3)^2 = 25.

But how can I make them local?


Solution

  • Here is one option. I also changed that assign stuff (creating a bunch of systematically named objects in the global environment is a clear sign to use a list instead).

    funs <- matrix(list(), 3, 2, dimnames = list(paste0("plus", 1:3), 
                                                 paste0("pow", 1:2)))
    
    for(i in 1:3){
      for(j in 1:2){
        create_fun <- function(i, j){
          #force evaluation so that the values are stored in the closure
          force(i); force(j) 
          function(x) (x+i)^j
        }
        funs[i, j][[1]] <- create_fun(i, j)
      }
    }
    
    funs["plus2", "pow1"][[1]](2)
    #[1] 4