【问题标题】:R environments and function call stacksR 环境和函数调用堆栈
【发布时间】:2012-09-11 14:46:00
【问题描述】:

我试图在一系列函数调用中使用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() 似乎不起作用。

【问题讨论】:

    标签: r scope environment-variables


    【解决方案1】:

    你被框架和环境之间的细微差别(由于框架是环境,或者环境是框架而更加微妙)以及lexical and dynamic scoping 之间的差异所困扰。 parent.frame 的帮助页面和分布在各种文档中的其他地方有一些详细信息。

    尝试简化:

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

    当你调用f1 并且它调用getter 然后getter 试图找到变量foo,它首先在它自己的环境中查找,没有找到它,然后在它的父环境中查找,它是全局的env 并找到值为 1 的 foo

    您的想法与框架近似的动态范围一致。当f1 被调用时,它会获得自己的环境(其中foo 将被赋值为2),然后它调用getter 函数。 foo的环境不是getter的env(词法作用域)的父框架,而是f1的环境是getter的父框架,因为getter是从f1调用的,所以在f1 的环境中查看你需要告诉get 函数在父框架中而不是在父环境中查看。

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

    【讨论】:

    • +1 很好的解释,谢谢。这应该是公认的答案,如果您合并我的代码解决方案,我将删除我的答案,以便您的答案可以被接受。
    • @Andrie 我认为这两个答案都很好,你的解决了眼前的问题,而我的给出了背景。我对剩下的两个都没有问题,哪个被接受应该是原始海报的决定。我非常感谢您的支持。
    【解决方案2】:

    如果你定义getter 在父框架中查找,它可以工作:

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

    然后:

    getter("foo")
    [1] 1
    
    f1()
    [1] 2
    

    【讨论】:

    • 成功了,谢谢!为什么 parent.frame() 有效但 sys.parent() 无效?是否有文档讨论所有这些不同功能的工作原理,以及按数字或按名称引用环境之间的区别?
    • @hgcrpd sys.parent 返回一个整数,而不是框架/环境。 parent.frame 使用 sys.parent 信息和 sys.frame 来获取帧(不仅仅是它的整数值)。
    猜你喜欢
    • 1970-01-01
    • 2015-11-09
    • 2019-11-22
    • 2014-01-17
    • 1970-01-01
    • 1970-01-01
    • 2014-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多