我正在编写一些用于执行重复任务的函数,但我正在尝试最小化加载数据的次数。基本上我有一个功能,它需要一些信息并制作一个情节。然后我有第二个函数循环并输出多个图到.pdf。在这两个函数中,我有以下代码行:
if(load.dat) load("myworkspace.RData")
其中load.dat
是逻辑的,我需要的数据存储在myworkspace.RData中。当我调用循环的包装函数并输出多个图时,我不想在每次调用内部函数时重新加载工作区。我以为我可以在包装函数中加载一次工作区,然后内部函数可以访问该数据,但是我收到了一个错误说明。
所以我的理解是当函数无法在其本地环境中找到变量时(在调用函数时创建),该函数将查找父环境中的变量。
我假设内部函数调用的父环境将是外部函数调用。显然这不是真的:
func1 <- function(...){
print(var1)
}
func2 <- function(...){
var1 <- "hello"
func1(...)
}
> func2()
Error in print(var1) : object 'var1' not found
在阅读了大量问题,语言手册和this非常有用的博文后,我想出了以下内容:
var1 <- "hello"
save(list="var1",file="test.RData")
rm(var1)
func3 <- function(...){
attach("test.RData")
func1(...)
detach("file:test.RData")
}
> func3()
[1] "hello"
有更好的方法吗?为什么func1
在func2
创建的本地环境中找不到未定义的变量,而func2
调用func1
时是什么?
注意:我不知道如何命名这个问题。如果有人有更好的建议,我会改变它并编辑这一行。
答案 0 :(得分:8)
要说明词汇范围,请考虑以下事项:
首先让我们创建一个沙盒环境,只是为了避免这么常见的R_GlobalEnv:
sandbox <-new.env()
现在我们在其中放入两个函数:f
,它查找名为x
的变量;和g
,定义了本地x
并调用了f
:
sandbox$f <- function()
{
value <- if(exists("x")) x else "not found."
cat("This is function f looking for symbol x:", value, "\n")
}
sandbox$g <- function()
{
x <- 123
cat("This is function g. ")
f()
}
技术性:在控制台中输入功能定义会导致封闭环境设置为R_GlobalEnv
,因此我们手动强制f
和g
的机箱匹配它们所处的环境“属于”:
environment(sandbox$f) <- sandbox
environment(sandbox$g) <- sandbox
致电g
。 x=123
找不到本地变量f
:
> sandbox$g()
This is function g. This is function f looking for symbol x: not found.
现在我们在全局环境中创建x
并调用g
。函数f
将首先在沙箱中查找x
,然后在沙箱的父级中查找,恰好是R_GlobalEnv:
> x <- 456
> sandbox$g()
This is function g. This is function f looking for symbol x: 456
为了检查f
在其附件中首先查找x
,我们可以在其中放置x
并致电g
:
> sandbox$x <- 789
> sandbox$g()
This is function g. This is function f looking for symbol x: 789
结论:R中的符号查找遵循封闭环境链,不在执行嵌套函数调用期间创建的评估框架。
的链接即可答案 1 :(得分:2)
你可以使用闭包:
f2 <- function(...){
f1 <- function(...){
print(var1)
}
var1 <- "hello"
f1(...)
}
f2()