Batato
Batato

Reputation: 568

Inject variables automatically in R function environment

Let's supposed we declare this function:

f <- function(x) u + x

now if I call f(10) R will look for the parent environment for a value of u recursively until it reaches the global environment, if a value is found u + 10 is returned, otherwise we get an error. So far so good.

Now supposed we have a pool from where we would like to pull the unknown values inside the body of f, like pool <- list(u = 10) or an environment variable with u set.

How would you inject the u value to a generic function f? Can you write a function that injects the variables defined in the pool inside f? In other words, can we point R in which direction to look for for missing variables instead looking up recursively in the parent environment?

EDIT: I know I can do this f <- function(x) pool[["u"]] + x of course, but I'm looking for the behavior described above.

EDIT: The use case is the following: I'm building a library that allow users to configure the function they would like to optimize, and I want them to be allowed to use certain variables already computed when the library is loaded (solutions of certain differential equations) and combine them as they wish. So I'd like to make the process as transparent as possible for them and let them use a variable value u instead of pool$u in the body of the function if possible.

Upvotes: 2

Views: 387

Answers (1)

G. Grothendieck
G. Grothendieck

Reputation: 269526

1) reset environment Convert pool to an environment and set the environment of f to it:

# inputs
pool <- list(u = 10)
f <- function(x) u + x

environment(f) <- list2env(pool, parent = environment(f))
f(1)
## [1] 11

2) proto Another possibility is to use the proto package. A proto object is an environment with modified methods. Convert pool to a proto object p and insert f into it. Inserting f into p resets its environment to p so:

library(proto)

p <- as.proto(pool, parent = environment(f))
p$f <- f 
with(p, f(10)) # use the version of f inserted into p
## [1] 11

or we could overwrite f with the version of f in p:

library(proto)

p <- as.proto(pool, parent = environment(f))
p$f <- f 
f <- with(p, f)
f(1)
## [1] 11

Update: Have set parent of new environment formed from pool to original environment of f so that free variables in f are first looked up in the environment formed from pool and then f's environment in that order rather than the environment derived from pool and then the parent frame.

Upvotes: 3

Related Questions