R 嵌套函数环境选择

R 嵌套函数环境选择,r,function,environment-variables,R,Function,Environment Variables,我正在编写一些用于执行重复任务的函数,但我正在尝试最小化加载数据的次数。基本上我有一个函数,它获取一些信息并绘制一个图。然后我有第二个函数,它将循环并将多个绘图输出到.pdf。在这两个函数中,我都有以下代码行: if(load.dat) load("myworkspace.RData") 其中,load.dat是一个逻辑文件,我需要的数据存储在myworkspace.RData中。当我调用循环并输出多个绘图的包装器函数时,我不希望在每次调用内部函数时都重新加载工作区。我以为我可以在包装器函数中

我正在编写一些用于执行重复任务的函数,但我正在尝试最小化加载数据的次数。基本上我有一个函数,它获取一些信息并绘制一个图。然后我有第二个函数,它将循环并将多个绘图输出到.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

func1您可以使用闭包:

f2 <- function(...){
   f1 <- function(...){
     print(var1)
   }
   var1 <- "hello"
   f1(...)
 }
 f2()

<代码> f2说明词法范围,考虑以下内容:

var1 <- "hello"
save(list="var1",file="test.RData")
rm(var1)

func3 <- function(...){
  attach("test.RData")
  func1(...)
  detach("file:test.RData")
}

> func3()
[1] "hello"
首先,让我们创建一个沙箱环境,只是为了避免非常常见的R_GlobalEnv:

sandbox <-new.env()
> x <- 456
> sandbox$g()
This is function g. This is function f looking for symbol x: 456 
技术性:在控制台中输入函数定义会使封闭环境设置为
R\u GlobalEnv
,因此我们手动强制
f
g
的封闭环境与它们“所属”的环境相匹配:

现在我们在全局环境中创建一个
x
,并调用
g
。函数
f
将首先在沙盒中查找
x
,然后在沙盒的父级中查找,该父级恰好是R_GlobalEnv:

sandbox <-new.env()
> x <- 456
> sandbox$g()
This is function g. This is function f looking for symbol x: 456 
结论:R中的符号查找遵循封闭环境链,而不是执行嵌套函数调用期间创建的计算框架


编辑:只需添加一个链接到

词法范围,意味着函数将在其父环境中查找未定义的符号,而父环境不一定是调用环境。请检查此链接:@Ferdinand.kraft谢谢您的链接。今天下午我将讨论这个问题。如果您的数据是以数据帧的形式存在的,则可以使用包
data.table
,并将您的表作为参数传递给
func1
内部
func3
。此程序包通过引用工作,不会生成不需要的数据副本。不太清楚为什么它看不到
var1
,但请注意
print(parent.frame()$var1)
工作正常。@dayne,故意让
func1
看不到这些环境。当您键入
func1时,我需要能够将内部函数用作独立函数。我不想每次调用外部函数时都重新定义内部函数(更不用说重复一堆代码了)。我认为最干净的设置是:将所有数据放在一个列表中(my_data),然后将其作为函数的参数。在函数内部,您可以使用(my_data,{})来避免额外的键入。这是我见过的最好的例子。非常感谢你!我没有真正理解环境和框架的区别。
> x <- 456
> sandbox$g()
This is function g. This is function f looking for symbol x: 456 
> sandbox$x <- 789
> sandbox$g()
This is function g. This is function f looking for symbol x: 789