您将“调用环境”与“封闭环境”混淆了。在 Hadley 的《Advanced R》一书中查看这些术语。
http://adv-r.had.co.nz/Environments.html
“调用环境”是调用函数的环境,由不幸命名的函数parent.frame 返回。但是,调用环境不用于词法作用域。
“封闭环境”是创建函数并用于词法作用域的环境。您已经在全局环境中创建了func1 和func2。因此,全局环境是两个函数的“封闭环境”,并将用于词法范围无论调用环境如何!!
如果您希望func2 使用func1 的执行环境进行词法作用域,您有(至少)两个选项。你可以在func1内创建func2
func1 <- function(vec) {
func2 <- function(foos) {
for (foo in foos)
print(eval(parse(text = foo)))
return(foos)
}
text3_obj <- 'text3'
vec <- c(vec, c('text3_obj'))
return(func2(vec))
}
然后您的测试按预期工作:
> text1_obj <- 'text1'
> text2_obj <- 'text2'
> func1(c('text1_obj', 'text2_obj'))
[1] "text1"
[1] "text2"
[1] "text3"
[1] "text1_obj" "text2_obj" "text3_obj"
或者,您可以创建func2 并从func1 中重新分配它的“封闭环境”。
func2 <- function(foos) {
for (foo in foos)
print(eval(parse(text = foo)))
return(foos)
}
func1 <- function(vec) {
text3_obj <- 'text3'
vec <- c(vec, c('text3_obj'))
environment(func2) <- environment()
return(func2(vec))
}
这也将按预期工作。
我在编写演示代码时发现的一个有趣的花絮...似乎当您从func1 中重新分配func2 的环境时,R 在@ 的执行环境中创建了func2 的副本987654337@。当您返回控制台时,原始func2 的封闭环境保持不变。证人:
a = function() {
print(identical(environment(a), globalenv()))
}
b = function(x) {
environment(a) <- environment()
a()
}
测试a() 和b():
> a()
[1] TRUE
> b()
[1] FALSE
> a()
[1] TRUE
>
这不是我所期望的,但似乎 R 的表现非常出色。如果不是这样,a() 的封闭环境将永久更改为b() 的执行环境,并且 FALSE 应该在第二次调用 a() 时返回。
事实证明,您可以在全局环境中使用<<- 强制更改为原始a():
a = function() {
print(identical(environment(a), globalenv()))
}
b = function(x) {
# set a variable in the execution environment of b() for use later...
montePython = "I'm not dead yet!!"
# change the enclosing environment of a() in the global environment
# rather than making a local copy of a() in b()'s execution environment.
environment(a) <<- environment()
a()
}
测试a() 和b():
> a()
[1] TRUE
> b()
[1] FALSE
> a()
[1] FALSE
>
有趣的是,这意味着b() 的(通常是临时的)执行环境即使在b() 终止后仍然存在于内存中,因为a() 仍然引用该环境,所以它不能被垃圾回收。证人:
> environment(a)$montePython
[1] "I'm not dead yet!!"