2014-03-03 44 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

相關問題