2012-09-19 58 views
7

我試圖在一系列函數調用使用get,但對象名稱查找似乎跳過環境。例如:[R環境和函數調用棧

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()似乎不起作用。

回答

6

如果定義getter在父框架看,它的工作原理:

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

然後:

getter("foo") 
[1] 1 

f1() 
[1] 2 
+1

這樣做,謝謝!爲什麼parent.frame()工作,但不是sys.parent()?是否有文檔討論所有這些不同功能的工作方式,以及通過編號或名稱提及環境的差異? – hgcrpd

+2

@hgcrpd'sys.parent'返回一個整數,而不是框架/環境。 'parent.frame'使用'sys.parent'信息和'sys.frame'來獲取幀(不只是它的整數值)。 –

13

您正在由框架和環境之間的細微差別絆倒了(這是因爲框架是環境,或者環境是框架,所以更加微妙)和lexical and dynamic scoping之間的區別。有關parent.frame的幫助頁面中的一些詳細信息以及遍佈各種文檔的其他地方。

要嘗試和簡化:

getter功能都有自己的environment其中的局部變量函數存儲(x在這種情況下)。由於R在詞彙範圍上,這意味着函數環境有一個父級環境,它由函數定義的位置定義,在這種情況下是全局環境(如果它是在另一個函數內定義的,那麼父級環境將是環境的env功能)。

當你打電話f1並呼籲getter然後吸氣試圖找到變量foo,它首先在自己的環境,並沒有找到它,那麼看起來這是全球env和發現foo與其父環境1.

你的思想價值而動態範圍界定的線,框架大致去。當f1把它叫做都有自己的環境(其內foo將被分配值2),那麼它調用getter功能。的foo環境不getter的ENV(詞法範圍)的母公司,但f1環境的getter父框架,因爲getterf1調用,所以看在f1的環境中,你需要告訴get函數查看父框架而不是父環境。

這裏的總結是父環境是定義函數的環境(詞法範圍),父框架是函數被調用的框架/環境(模擬動態範圍)。

+2

+1非常好的解釋,謝謝。這是值得接受的答案,如果您將我的代碼解決方案合併,我將刪除我的答案,以便您的答案得到接受。 – Andrie

+0

@Andrie我認爲這兩個答案都很好,你的解決了眼前的問題,我的背景。我對剩餘的兩個都沒有問題,哪個被接受應該是原始海報的決定。我很欣賞你的讚揚。 –

+0

感謝這兩個,這是非常有益的。 – hgcrpd