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)
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