Search code examples
rfunctionnamespacesnse

R: hard code the content of a variable inside a function


I would like to create a function using the value stored in a variable, but in a way that I paste the "content" of that variable rather than the variable call, so that once the variable is re-assigned, the function doesn't change.

Is there an elegant way of doing that?

var <- 3
f <- function(x) var + x

f(1)
#> [1] 4

var <- 1

f(1)  # I would like the output to stay the same, i.e., the function to be "fixed" after its creation
#> [1] 2

Created on 2021-06-08 by the reprex package (v1.0.0)


Solution

  • In R you would create a closure using one of these methods. You could define a local environment and copy var there

    f <- local({var; function(x) var + x})
    

    Or you could do a similar thing with an in-line function

    f <- local({var; function(x) var + x})
    

    Or you can split that version up into a generator function

    make_f <- function(var) function(x) var + x
    f <- make_f(var)
    

    All of these will freeze the value of var inside the function f.

    You could also write a helper function that would be more explicit about the environment creation

    freeze_var <- function(fun, ..., .env=environment(fun)) {
      mc <- match.call(expand.dots = FALSE)
      dnames <- sapply(mc$..., deparse)
      fenv <- new.env(parent=.env)
      list2env(setNames(list(...), dnames), envir = fenv)
      environment(fun) <- fenv
      fun
    }
    

    Then you could use it to wrap any function with any variable(s)

    var <- 3
    f <- function(x) var + x
    ff <- freeze_var(f, var)
    
    f(1)
    # [1] 4
    ff(1)
    # [1] 4
    
    var <- 1
    f(1)
    # [1] 2
    ff(1)
    # [1] 4