我有一个在其父环境中获取脚本的函数。以下内容按预期工作:
cat("aa <- 77", file="script.R")
runScript <- function() source("script.R", local=parent.frame())
env <- new.env()
evalq(runScript(), envir=env)
ls.str(envir=env) # as expected: aa in env, not in globalEnv
rm(env)
Run Code Online (Sandbox Code Playgroud)
当我将其包装在函数中时,环境似乎被忽略:
thisfails <- function(expr){
env <- new.env()
evalq(expr, envir=env)
ls(envir=env)
}
thisfails(runScript()) # why is aa in globalEnv?
rm(aa)
Run Code Online (Sandbox Code Playgroud)
现在我可以用 来理解这一点eval,但不能用 来理解evalq,正如手册所说:eval 在将其传递给求值器之前评估当前作用域中的第一个参数: evalq 避免了这种情况。
有趣的是,这有效:
works <- function(){
runScript()
ls()
}
works() # as expected: returns aa, doesn't create it in globalEnv
Run Code Online (Sandbox Code Playgroud)
如何在函数内使用 runScript 作为表达式并避免在 globalEnv 中对其求值?
这会失败,因为您的函数thisfails 本身正在使用标准评估:在传递给之前expr进行评估。evalq
相反,您需要通过 捕获未计算的参数substitute,并将结果表达式传递给eval:
this_works <- function (expr) {\n env <- new.env()\n eval(substitute(expr), envir = env)\n ls(envir = env)\n}\nRun Code Online (Sandbox Code Playgroud)\n令人困惑的是,这看起来与evalq! \xe2\x80\x94\xc2\xa0 毕竟,evalq(expr)实现为:
.Internal(eval(substitute(expr), envir, enclos))\nRun Code Online (Sandbox Code Playgroud)\n然而,认为等同evalq(expr)于 更为准确eval(quote(expr))。也就是说,逐字expr理解,并且从不评估。的实际实现看起来有所不同,只是因为它需要首先检索调用范围中由其参数表示的未计算表达式,而 \xe2\x80\x99 正是在参数上调用时执行的操作。evalqexprsubstitute
\xe2\x80\xa6 令人困惑的是,对全局环境中的名称执行不同的substitute操作;也就是说,它让它们保持不变:
x = 1\nsubstitute(x + 2)\n# x + 2\n\nin_function = function () {\n x = 1\n substitute(x + 2)\n}\n\nin_function()\n# 1 + 2\n\nin_env = new.env()\nin_env$x = 1\nsubstitute(x + 2, in_env)\n# 1 + 2\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
56 次 |
| 最近记录: |