R环境和函数调用堆栈

时间:2012-09-19 09:44:40

标签: r scope environment-variables

我试图在一系列函数调用中使用get,但查找对象名称似乎跳过了环境。例如:

foo <- 1 # variable in .GlobalEnv

getter <- function(x) {get(x)}
getter("foo") # returns 1, which is expected

f1 <- function() {
  foo <- 2 # local variable in the function scope
  getter("foo")
}

f1() # still returns 1, would've expected to return 2

为什么调用f1会返回全局环境中的foo而不是调用函数环境中的foo

如何get查看调用函数的环境?设置pos = sys.parent()似乎不起作用。

2 个答案:

答案 0 :(得分:14)

你被框架和环境之间的微妙差异所绊倒(由于框架是环境,或者环境可能是框架,因此更加微妙)以及lexical and dynamic scoping之间的差异。 parent.frame的帮助页面中有一些详细信息,其他地方也有各种文档。

尝试简化:

您的getter函数有自己的environment,其中存储了该函数的本地变量(在这种情况下为x)。由于R是词法范围,这意味着函数环境具有父环境,该环境由定义函数的位置定义,在这种情况下是全局环境(如果它是在另一个函数内部定义的那么父环境将是env for the功能)。

当您致电f1并调用getter时,getter会尝试查找变量foo,它首先在自己的环境中查找,但在那里找不到它,然后查看其中父环境,它是全局环境并查找foo,其值为1.

你的想法与动态范围有关,框架是近似的。调用f1时,它会获得自己的环境(foo将为其分配值2),然后调用getter函数。 foo的环境不是getter的env(词法范围)的父级,但f1的环境是getter的父框架,因为getterf1调用,所以要查看f1的环境,你需要告诉get函数查看父框架而不是父框架。

总结是父环境是定义函数的环境(词法范围),父框架是调用函数的框架/环境(模拟动态范围)。

答案 1 :(得分:6)

如果您定义getter以查看父框架,则可以正常工作:

getter <- function(x) get(x, envir=parent.frame())

然后:

getter("foo")
[1] 1

f1()
[1] 2