我试图通过将所有必要的依赖项(函数和数据)加载到新环境中并在该环境中评估表达式,以沙盒方式运行一大块R代码.但是,我在调用环境中的其他函数时遇到了麻烦.这是一个简单的例子:
jobenv <- new.env(parent=globalenv())
assign("f1", function(x) x*2, envir=jobenv)
assign("f2", function(y) f1(y) + 1, envir=jobenv)
expr <- quote(f2(3))
Run Code Online (Sandbox Code Playgroud)
使用evalon expr失败,因为f2找不到f1
> eval(expr, envir=jobenv)
Error in f2(3) : could not find function "f1"
Run Code Online (Sandbox Code Playgroud)
而明确附加环境是有效的
> attach(jobenv)
> eval(expr)
[1] 7
Run Code Online (Sandbox Code Playgroud)
我可能错过了一些明显的东西,但我找不到任何有效的eval呼叫排列.有没有办法在不附加环境的情况下获得相同的效果?
有很多方法可以做到这一点,但我有点像这样:
jobenv <- new.env(parent=globalenv())
local({
f1 <- function(x) x*2
f2 <- function(y) f1(y) + 1
}, envir=jobenv)
## Check that it works
ls(jobenv)
# [1] "f1" "f2"
local(f2(3), envir=jobenv)
# [1] 7
eval(quote(f2(3)), envir=jobenv)
# [1] 7
Run Code Online (Sandbox Code Playgroud)
作用域是在创建函数时定义的,而不是在调用函数时定义的。请参阅R简介手册的10.7节。
这对我来说似乎有点奇怪,但是即使您避免assign一起使用而只是使用,您也会得到相同的行为$<-。
jobenv <- new.env(parent=globalenv())
jobenv$f1 <- function(x) x*2
jobenv$f2 <- function(y) f1(y) + 1
expr <- quote(f2(3))
eval(expr, envir=jobenv)
Run Code Online (Sandbox Code Playgroud)
这似乎是因为封闭的环境f1,并f2为全球环境。我本来希望如此jobenv。
> environment(jobenv$f1)
<environment: R_GlobalEnv>
> environment(jobenv$f2)
<environment: R_GlobalEnv>
Run Code Online (Sandbox Code Playgroud)
一种解决方案是显式设置每个函数的环境...但是必须有一种更简单的方法。
> environment(jobenv$f1) <- jobenv
> environment(jobenv$f2) <- jobenv
> eval(expr, envir=jobenv)
[1] 7
Run Code Online (Sandbox Code Playgroud)