2016-11-23 57 views
1
fa <- function(x){x+1} 
fb <- function(x){x-1} 

f1 <- function(x, y){f(x)^y} 

f2 <- function(x, ab, y){ 
    if(ab == 'a'){ 
    f <- fa 
    } else { 
    f <- fb 
    } 
    f1(x, y) 
} 

f2(0, 'a', .5) 
Error in f1(x, y) : could not find function "f" 

因爲ff1的環境中定義的上述不起作用。功能無法「看到」在全球環境中定義等功能

什麼是使這項工作的好方法?這

  • 避免了在全球環境中通過一切f2的環境
  • 避免了重新定義函數內f2(這將是一個麻煩,並創建複製/粘貼錯誤的機會)

定義某種「子全局」環境是否有意義,並將我希望每個人都在此環境中使用的東西放在一起,然後讓每個函數都能夠訪問「子全局」中的東西?然後以某種方式確保subglobal始終是全球的一個嚴格子集?如果明智的話,我會如何做到這一點?

+0

一個讓所有東西都能正常工作的黑客修復,可以在調用'f2'內的'f1'之前在'line'使用'environment(f1)= environment()',因爲'f1'在'f' '環境(F1)'。順便說一下,全局'f1'不會受到'f2'中的這種改變的影響。儘管我同意康拉德的觀點,不管是將明確的職能作爲論據,還是採用類別制度,如果方便的話。 –

回答

7

的,因爲fafb沒有在f2的環境中定義上面不起作用。

不 - 他們。該錯誤是完全不同的:

f1 <- function(x, y){f(x)^y} 

在這裏,您使用的是未定義的變量f,這是一個錯誤。

你有一個不同的變量(容易也叫f)內f2。但是,這與f1無關,因爲f1f2不共享其本地變量。如果你想通過f2ff1那麼你需要將它作爲參數傳遞。

順便說一句,變量名稱如此相似這一事實使得這個過程比必要的更復雜。如果你改變你的代碼下面,等效代碼,問題就變得更加清晰:

plus1 = function (x) x + 1 
minus1 = function (x) x - 1 

f_exp = function (x, y) g(x)^y 

plusminus_exp = function (x, ab, y) { 
    if (ab == 'a') 
     f = plus1 
    else 
     f = minus1 
    f_exp(x, y) 
} 

plusminus_exp(0, 'a', .5) 
# Error in f_exp(x, y) : could not find function "g" 

而這裏的修復:

f_exp = function (x, y, g) g(x)^y 
f_exp(x, y, f) 

另外,如果你調用f_exp許多在plusminus_exp之內,你可以使用一些更高級的抽象創建一個函數生成器:一個返回另一個函數的函數:

make_f_exp = function (f) { 
    force(f) 
    function (x, y) 
     f(x)^y 
} 

plusminus_exp = function (x, ab, y) { 
    f = if (ab == 'a') plus1 else minus1 
    f_exp = make_f_exp(f) 
    f_exp(x, y) 
} 

這使得f_exp可插拔但隔離效果,以避免引入一個全局修改狀態。這是功能性編程語言的非常標準的代碼,但在功能性語言之外很少見,因此對某些人來說有點令人驚訝。

+0

嗯,我的真實代碼比我愚蠢的SO例子有更好的名字來顯示我的問題。但是,這是事情:我想找到一種方法,不必將參數'f'傳遞給'f1'(或者,如果您願意,可以使用'called_directly')。我想設置'f'的定義作爲頂層函數的參數,然後讓所有東西隨後「正常工作」 –

+1

@generic_user這是一個錯誤:您打算做什麼創建[可變全局狀態] (http://softwareengineering.stackexchange.com/q/148108/2366),這意味着您將在此代碼中尋找其餘存在的奇怪錯誤。你可以做的是創建一個'make_f1'函數,它將一個函數作爲參數並返回一個不同的函數。看到我更新的答案。 –

+0

@generic_user順便說一句,你所說的「subglobal」環境基本上就像一個類。如果是這樣,請檢查函數式編程,特別是R的R6系統。這通常應該避免,並且保留用於實際需要維護大型可變狀態對象的情況。 –