2015-04-24 224 views
1

我不理解爲什麼R中一個全球範圍的列表中,不能從一個函數中作如下修改:全局變量和範圍 - R的

global <<- list() 

f <- function(x) { 
    global[[x]] <- "blah" 
} 

f(1) 
f(2) 
print(global) 

輸出是

list() 

不過,我期待的輸出:

[[1]] 
[1] "blah" 

[[2]] 
[1] "blah" 

這是爲什麼?我是否必須聲明列表中的每個元素都是全局的?

對於在功能塊外部聲明的局部範圍變量,似乎也是如此。

謝謝!

+6

'<< - '應該在你的函數裏面 –

回答

2

基本上,因爲你使用的是「< - 」分配的功能創建函數的範圍內使用的「全球」變量的副本。

這可以通過在第二個函數g()中添加,它在f()打印出來之前改變'global'的值,但這次使用「< < - 」賦值。在f()的第一行創建您的F(x)的「全球性」的局部範圍的副本,然後您更新的「全球性」使用G(X)在全球複製。

global <<- list() 

f <- function(x) { 
    global[[x]] <- "blah" 
    g(x) 
    global 
} 

g <- function(x){ 
    global[[x]] <<- "newblah" 
} 


f(1) #prints 'blah', despite the fact the g(x) has already updated the value 

global #prints 'newblah' 

如果f(x)仍然引用'global'的全局副本,它會打印g(x)中指定的「newblah」。相反,它打印這是在F(X)分配到的全球'的局部範圍的副本中的值。

然而,印刷「全球性」的任何功能外示出了G(X)沒有實際上更新「全球性」的全局複製的值。

現在,如果你移動內部F G(X)(X),則f(x)是現在G的父(X)。在這種情況下,「< < - 」分配給f(x)範圍內的'global'的值。所以'全局'的全局副本仍然是空的,但是如果你在f()的範圍內輸出'global',你會得到更新後的值。

global <<- list() 

f <- function(x) { 
    global[[x]] <- "blah" 

    g <- function(x){ 
    global[[x]] <<- "newblah" 
    } 

    g(x) 
    global 
} 



f(1) #prints 'newblah' 

global #empty 
3

我相信你只是對<<-實際上有點困惑。從help("<<-")

的操作符< < - 和 - >>通常只在函數中使用,和 導致搜索以通過親環境中的被分配的變量的現有 定義製成。如果發現這樣一個變量 (並且其綁定未鎖定),則其值被重新定義,否則 賦值發生在全局環境中。

所以應該清楚,<<-無論在哪裏運行,都不會創建「全局變量」。的確,R並不是真的如此。

相反,<<-執行一種「全局分配」,允許您修改當前範圍以外的變量。

這是一種粗糙版本的更精確assign()。通常不鼓勵使用這兩種工具,因爲它們傾向於破壞R使用的功能性編程範例(即無副作用)。像其他任何東西一樣,它們有它們的用途,但通常不用於常規變量處理。