使用功能和环境

Edu*_*oni 3 scope r

这里在最近的讨论(如1,2)我现在用在我的一些代码的环境.我的问题是,如何根据参数创建修改环境的函数?例如:

y <- new.env()
with(y, x <- 1)
f <- function(env,z) {
    with(env, x+z)
}
f(y,z=1)
Run Code Online (Sandbox Code Playgroud)

Error in eval(expr, envir, enclos) : object 'z' not found
Run Code Online (Sandbox Code Playgroud)

我正在使用环境来同时保持两组模拟(没有重构我的代码,我为一组实验编写了代码).

Sha*_*ane 8

最简单的解决方案是在引用对象时使用环境:

y <- new.env()
y$x <- 1
f <- function(env,z) {
    env$x+z
}
f(y,z=1)
Run Code Online (Sandbox Code Playgroud)

您还需要分配z给您的环境.

y <- new.env()
with(y, x <- 1)
f <- function(env,z) {
    assign("z", z, envir=env)
    with(env, x+z)
}
f(y,z=1)
Run Code Online (Sandbox Code Playgroud)

另一个选择是attach您的环境,以便现在可以直接使用变量.

y <- new.env()
with(y, x <- 1)
f <- function(env,z) {
    attach(env)
    y <- x + z
    detach(env)
    y
}
f(y,z=1)
Run Code Online (Sandbox Code Playgroud)

后一种解决方案功能强大,因为它意味着您可以在新环境中使用任何附加环境中的任何对象,但这也意味着您需要非常小心全局分配的内容.

编辑:

这很有趣,我并不完全理解这种行为(即为什么z不在with调用的范围内).它与最初创建环境有关,导致它超出了函数的范围,因为这个版本有效:

f <- function(z) {
    y <- new.env()
    with(y, x <- 1)
    with(y, x+z)
}
f(y,z=1)
Run Code Online (Sandbox Code Playgroud)

  • 原因是当'en'在'env'中被评估而未找到时,它所看到的下一个地方就是封闭的环境/范围.封闭范围不是f()而是全局环境,因为词法或静态范围规则表明封闭范围是在创建时确定的(因此是静态的),而不是在评估时(动态范围). (2认同)