2014-03-03 43 views
9

我当时正在玩弄R,并注意到与全球环境中与实际全球环境不同的函数调用有些不一致。在函数调用中与R的全局环境不一致

考虑以下几点:

> test = function() 
+ { 
+  print(environmentName(as.environment(-1))) 
+  print(ls(as.environment(-1))) 
+  print(environmentName(.GlobalEnv)) 
+  print(ls(.GlobalEnv)) 
+  as.environment(-1) 
+ } 
> foo = 1 
> ls() 
[1] "foo" "test" 
> test() 
[1] "" 
[1] "doTryCatch" "expr"  "handler" "name"  "parentenv" 
[1] "R_GlobalEnv" 
[1] "foo" "test" 
<environment: R_GlobalEnv> 

在函数调用,as.environment(-1)返回声称它是<environment: R_GlobalEnv>但调用environmentName当上说的环境,它的名字是一个空字符的环境。此外,它的内容不同于真实的全球环境。这里到底发生了什么?

我首先注意到在调用中使用mget的错误,因为找不到全局定义的变量。这似乎与直觉相反,因为通常当在函数中引用变量时,R将在封闭环境中向上搜索,直到找到包括全局环境的变量的定义。

+2

看来,'不需要environmentName'显示这种差异。这两个打印语句给出了不同的结果: 'test < - function(){e < - as.environment(-1);印刷(E); print(as.environment(-1))}; test()' –

+0

同样比较:'print(as.environment(-1)); I(as.environment(-1)); C(as.environment(-1))'。他们都给出了不同的结果,可能与他们如何以及在哪里评估他们提供的论点有关,尽管我不清楚发生了什么事情。相关的C级源代码是[here](https://github.com/wch/r-source/blob/trunk/src/main/envir.c#L2833)和[here](https:// github。 COM/WCH/R-源/斑点/中继/ SRC /主/ envir.c#L2789)。 (后者提到了'as.environment(-1)'和'pos.to.env(-1)'的等价性。) –

回答

4

这是懒惰的评估结果:

test <- function() { 
    e <- as.environment(-1) 

    list(
    lazy = ls(as.environment(-1)), 
    eager = ls(envir = e) 
) 
} 

foo <- 1 
test() 
#> $lazy 
#> [1] "doTryCatch" "expr"  "handler" "name"  "parentenv" 
#> 
#> $eager 
#> [1] "foo" "test" 
+2

您能详细说明一下吗?不应该在父框架中评估'as.environment(-1)',因为它是'ls'的显式参数?懒惰是如何进入的呢?在定义闭包而不强制参数时,我认为这主要是一个问题。对不起,在这里密集。 – BrodieG

+2

这仍然看起来像R.' as.environment(-1)'中的一个bug应该相对于承诺的环境来评估,但它似乎不是。 –

+1

这绝对不是一个错误。我将在明天当我在计算机上添加更多解释 – hadley

相关问题