根据最近的讨论(例如1,2)我现在正在使用某些代码中的环境。我的问题是,如何根据参数创建修改环境的函数?例如:
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
我正在使用环境来同时保留两组模拟(没有重构我的代码,我为一组实验编写了这些代码)。
答案 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