我对 R 语言中的函数环境有疑问。我知道每次在 R 中调用函数时,都会创建一个新的环境 E 来执行函数体。E 的父链接指向创建函数的环境。
我的问题:是否有可能以某种方式指定环境 E,即,可以提供一个特定的环境来执行函数吗?
我对 R 语言中的函数环境有疑问。我知道每次在 R 中调用函数时,都会创建一个新的环境 E 来执行函数体。E 的父链接指向创建函数的环境。
我的问题:是否有可能以某种方式指定环境 E,即,可以提供一个特定的环境来执行函数吗?
函数具有可以从函数外部更改的环境,但不能在函数本身内部更改。环境是函数的一个属性,可以使用environment()
. 一个函数最多有一个环境,但您可以在不同的环境中复制该函数。
让我们用 x 的值设置一些环境。
x <- 0
a <- new.env(); a$x <- 5
b <- new.env(); b$x <- 10
以及从环境foo
中使用的功能x
foo <- function(a) {
a + x
}
foo(1)
# [1] 1
现在我们可以编写一个辅助函数,我们可以用它来调用任何环境的函数。
with_env <- function(f, e=parent.frame()) {
stopifnot(is.function(f))
environment(f) <- e
f
}
这实际上返回了一个分配了不同环境的新函数(或者如果未指定,它使用调用环境),我们可以通过传递参数来调用该函数。观察
with_env(foo, a)(1)
# [1] 6
with_env(foo, b)(1)
# [1] 11
foo(1)
# [1] 1
这是解决问题的另一种方法,直接取自http://adv-r.had.co.nz/Functional-programming.html
考虑代码
new_counter <- function() {
i <- 0
function() {
i <<- i + 1
i
}
}
(更新以提高准确性)外部函数创建一个环境,将其保存为变量。调用这个变量(一个函数)有效地调用了内部函数,它更新了与外部函数关联的环境。(我不想直接复制 Wickham 的整个部分,但我强烈建议任何有兴趣的人阅读标题为“可变状态”的部分。我怀疑你可能会比这更有趣。例如,这里是一个带有重置选项的修改:
new_counter <- function() {
i <- 0
function(reset = FALSE) {
if(reset) i <<- 0
i <<- i + 1
i
}
}
counter_one <- new_counter()
counter_one()
counter_one()
counter_two <- new_counter()
counter_two()
counter_two()
counter_one(reset = TRUE)
我不确定我是否完全跟踪问题的目标。但是可以设置函数执行的环境,修改该环境中的对象,然后从全局环境中引用它们。这是一个说明性示例,但我不知道这是否回答了提问者的问题:
e <- new.env()
e$a <- TRUE
testFun <- function(){
print(a)
}
testFun()
结果:打印错误(a):找不到对象'a'
testFun2 <- function(){
e$a <- !(a)
print(a)
}
environment(testFun2) <- e
testFun2()
返回:假
e$a
返回:假