In the following example I'm building a function factory, my issue is that my manufactured function is not considering the definition of x that I want :
foo <- function(){
x <- "x def in foo"
function(expr){
y <- "y def in bar"
eval(substitute(expr))
}
}
x <- "x def in global"
bar <- foo()
bar(c(x,y))
# [1] "x def in foo" "y def in bar"
I found 3 different ways of dealing with this, but I'm not sure which or if either of those is idiomatic or if they come with caveats.
I can set the environment of my manufactured function to .GlobalEnv
:
foo <- function(){
x <- "x def in foo"
bar <- function(expr){
y <- "y def in bar"
eval(substitute(expr))
}
environment(bar) <- .GlobalEnv
bar
}
x <- "x def in global"
bar <- foo()
bar(c(x,y))
# [1] "x def in global" "y def in bar"
Or I can cleanup my enclosing environment with on.exit
foo <- function(){
x <- "x def in foo"
on.exit(rm(list=ls())) # or on.exit(rm(x))
function(expr){
y <- "y def in bar"
eval(substitute(expr))
}
}
x <- "x def in global"
bar <- foo()
bar(c(x,y))
# [1] "x def in global" "y def in bar"
Or I can evaluate within a restricted environment, setting enclos
in the parent frame of bar
:
foo <- function(){
x <- "x def in foo"
function(expr){
y <- "y def in bar"
eval(substitute(expr),
envir = list(y = y),
enclos = parent.frame(2))
}
}
x <- "x def in global"
bar <- foo()
bar(c(x,y))
# [1] "x def in global" "y def in bar"
It seems to me that the second solution might be the cleanest as I think other solutions clutter the memory with the "x def in foo"
value , but maybe there are other better options or I'm overlooking something ?