R环境和函数调用堆栈

hgc*_*rpd 7 scope r 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
Run Code Online (Sandbox Code Playgroud)

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

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

Gre*_*now 14

框架和环境之间的微妙差异(由于框架是环境,或者可能是环境是框架)以及词法和动态范围之间的差异,您将被绊倒.帮助页面中有一些详细信息parent.frame以及遍布各种文档的其他地方.

试图简化:

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

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

你的想法沿着动态范围界定,框架是近似的.当f1调用它时,它会获得自己的环境(在其中foo将赋值2),然后调用该getter函数.环境foo不是getterenv(词法范围)f1的父级,但是环境是getter自从getter被调用以来的父框架f1,所以要在环境中f1查看你需要告诉get函数在父框架中查找比父环境.

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

  • +1非常好的解释,谢谢.这应该是公认的答案,如果你合并我的代码解决方案,我会删除我的答案,所以你的答案可以被接受. (2认同)

And*_*rie 6

如果您定义getter查看父框架,它的工作原理如下:

getter <- function(x) get(x, envir=parent.frame())
Run Code Online (Sandbox Code Playgroud)

然后:

getter("foo")
[1] 1

f1()
[1] 2
Run Code Online (Sandbox Code Playgroud)

  • @hgcrpd`sys.parent`返回一个整数,而不是帧/环境.`parent.frame`使用`sys.parent`信息和`sys.frame`来获取帧(而不仅仅是它的整数值). (2认同)