使用功能和环境

时间:2010-04-15 14:55:53

标签: r scope

根据最近的讨论(例如12)我现在正在使用某些代码中的环境。我的问题是,如何根据参数创建修改环境的函数?例如:

y <- new.env()
with(y, x <- 1)
f <- function(env,z) {
    with(env, x+z)
}
f(y,z=1)

引发

Error in eval(expr, envir, enclos) : object 'z' not found

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

3 个答案:

答案 0 :(得分:8)

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

y <- new.env()
y$x <- 1
f <- function(env,z) {
    env$x+z
}
f(y,z=1)

您还需要将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)

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

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

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

修改

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

f <- function(z) {
    y <- new.env()
    with(y, x <- 1)
    with(y, x+z)
}
f(y,z=1)

答案 1 :(得分:3)

您只需进行一项更改即可使您的示例正常工作 - 重新定义您的函数,以使用substitute()来“修复”f()范围内的所需值:

f <- function(env,z) {
    eval(substitute(x+z,list(z=z)), env)
}

这很快就会变得模糊,特别是因为你甚至可以在substitute()中包含赋值语句(例如,将x+z替换为y <- x+z,而不是在这里完全相关)但是这个选择可以由开发人员制作......

此外,您可以将上面的替换表达式中的list(z=z)替换为environment()(例如substitute(x+z,environment())),只要您在传递给{{{0}之间没有冲突的变量名称。 1}}以及那些居住在'env'中的人,但你可能不想太过分了。

编辑:以下是另外两种方式,第一种方式只是为了展示操纵环境的灵活性,第二种方式实际上更合理。

1)修改'env'的封闭环境(但在退出函数之前将其更改回原始值):

f()

2)强制评估函数的当前环境中的'z'(使用f <- function(env,z) { e <- environment(env) environment(env) <- environment() output <- with(env,x+z) environment(env) <- e output } ),而不是在评估'env'中的表达式environment()后让它保持为自由变量。

x+z

根据您所需的分辨率顺序,如果符号 - 值关联冲突 - 例如,如果您在功能环境和您创建的环境中都定义了'x',则为'y'('x'的值为'x'你希望它假设?) - 你可以改为将函数体定义为f <- function(env,z) { with(environment(),with(env,x+z)) }

答案 2 :(得分:1)

 y <- new.env()
 with(y, x <- 1)
 f <- function(env,z) {
    with(env, x+z)
 }
 f(y,z=1)

请注意括号:)以下内容适用:

with(env, x)+z