2012-07-31 28 views
2

我在R工作,我想做的事,例如,是否有可能使函數識別上面的範圍中的變量?

printx <- function() { 
    x <- 1 
    printy() 
    return(x) 
} 

printy <- function() { 
    print(x) 
} 

,因爲我不想讓身邊掠過噸的變量(也有在全球環境中的NO x) 。有沒有辦法做到這一點?所有功能都可以訪問全球環境,但功能環境和全球環境之間的關係呢?

回答

5

也許

printx <- function() { 
    x <- 1 
    printy() 
    return(x) 
} 

printy <- function() { 
    print(get('x',envir=parent.frame())) 
} 

> x<-0 
> printy() 
[1] 0 
> printx() 
[1] 1 
[1] 1 

這將使用x通過將其與調用函數在環境相關printy打印。

另外一個可能性是創建一個新的環境

e1<-new.env(parent = baseenv()) 

> assign('x',12,envir=e1) 
> x 
[1] 0 
> get('x',e1) 
[1] 12 
+3

打倒我吧。做得好。但是請注意,這不是一個好主意(http://stackoverflow.com/questions/5526322/examples-of-the-perils-of-globals-in-r-and-stata)。傳遞參數列表會更好,並且不會有太多麻煩。 – 2012-07-31 00:59:22

+0

@ AriB.Friedman:傳遞環境是另一種選擇,但您必須小心,不要無意中修改環境中的變量,因爲它們不是按值傳遞的。 – 2012-07-31 01:25:06

+0

這也是一個不錯的選擇。連同@邁克爾的答案,使三種選擇。歡呼問題背後的問題。 – 2012-07-31 01:48:31

3

您可以使用閉包來獲得類似的結果,而沒有與提及的abov風險相關的風險即不知道你想要做什麼,很難提出一個相關的例子。但是,下面的代碼可能會感興趣......

create.functions <- function(x){ 
    list(
     function() x, 
     function() x+1, 
     function() x^2 
    ) 

} 

x <- 0 

f1 <- create.functions(5) 
f1[[1]]() 
[1] 5 
f1[[2]]() 
[1] 6 
f1[[3]]() 
[1] 25 

f2 <- create.functions(3) 
f2[[1]]() 
[1] 3 
f2[[2]]() 
[1] 4 
f2[[3]]() 
[1] 9 

x 
[1] 0 

注意,您可以創建一套功能共享相同的參數,X,沒有參數x和x的全球環境中的值之間的任何衝突。如果您需要一組新函數,其中參數x的定義不同,您可以創建一個新的函數集。

這甚至可以制定這樣的代碼依託套件的功能上更改參數值時,不需要編輯:

f <- create.functions(5) 
f[[1]]()/f[[3]]() 
[1] 0.2 

f <- create.functions(3) 
f[[1]]()/f[[3]]() 
[1] 0.3333333 

注意的代碼f[[1]]()/f[[3]]()同一行,返回這取決於不同的結果關於你的參數x是如何定義的。