2017-02-21 77 views
4

在我回答我的問題之前,有一段序言,請和我一起!修改其他包中的函數類是不明智的嗎?

對於我正在研發的R包,我希望儘可能簡化用戶對partially apply函數的內聯。我有使用[]運算符來調用我的部分應用程序函數的想法,我已經命名爲「partialApplication」。我的目標是實現是這樣的:

dnorm[mean = 3](1:10) 
# Which would be exactly equivalent to: 
dnorm(1:10, mean = 3) 

爲了實現這一點,我試圖限定用於類功能的對象的新[]的方法,即

`[.function` <- function(...) partialApplication(...) 

然而,R給出警告,所述[]函數對象的方法被「鎖定」。 (有沒有什麼方法可以覆蓋這個?)

我的想法似乎被挫敗了,但我想到了一個簡單的解決方案:我可以發明一個新的S3類「partialAppliable」併爲其創建一個[]方法,即

`[.partialAppliable` = function(...) partialApplication(...) 

然後,我可以採取任何我想要的功能,並將'partialAppliable'追加到它的類中,現在我的方法將工作。

class(dnorm) = append(class(dnorm), 'partialAppliable') 
dnorm[mean = 3](1:10) 
# It works! 

現在,這裏是我的問題/問題:我希望用戶能夠使用任何他們想要的功能,所以我想,如果通過活動環境中的所有對象(使用LS)我環路和將「partialAppliable」附加到所有函數的類中?例如:

allobjs = unlist(lapply(search(), ls)) 
#This lists all objects defined in all active packages 

for(i in allobjs) { 
    if(is.function(get(i))) { 
     curfunc = get(i) 
     class(curfunc) = append(class(curfunc), 'partialAppliable') 
     assign(i, curfunc) 
    } 
} 

Voilà!有用。 (我知道,我應該將修改過的功能重新分配到它們的原始包裝環境中,但是您可以看到圖片)。

現在,我不是一個專業的程序員,但我已經意識到做這種事情(全局修改所有包中的所有變量)通常被認爲是不明智的/冒險的。但是,我想不出任何會出現的具體問題。所以這是我的問題:這樣做可能會產生什麼問題?任何人都可以想到通過這樣做會破壞的特定函數/包?

謝謝!

+0

而不是修改,你可以嘗試建立一個簡單的S3系統 - 例如(x)結構(x,class = c(「partiallyApplicable」,class(x))); 「[.partiallyApplicable」= function(x,...){formals(x)[names(list(...))] = as.list(substitute(list(...)))[ - 1]; return(x)}',這樣一個函數可以明確地獲得一個「class」屬性;並使用它作爲'partialapplicable(dnorm)[mean = 4 - 1,sd = sqrt(pi + 1)](1:5)' –

回答

1

這與Defaults package所做的相似。該軟件包被歸檔,因爲作者認爲修改其他軟件包的代碼是「非常糟糕的事情」。我想大多數人會同意。只因爲你可以這樣做,並不意味着這是一個好主意。

而且,不,你當然不應該將修改的功能分配回它們原來的軟件包環境。 CRAN不喜歡程序包不必要地修改用戶搜索路徑,所以如果他們允許程序包修改其他程序包的函數參數,我會感到驚訝。

您可以通過將所有已修改的函數放在搜索路徑的環境中來解決此問題。但是,您必須確保首先搜索環境,這意味着每次加載其他程序包時都要修改搜索路徑。

更改其他軟件包中函數的參數也有可能使其他軟件包很難再現您的結果,因爲它們必須包含所有參數設置。除非你總是用指定的所有參數來調用函數,否則這會破壞你想要做的事情的目的。

+0

謝謝!事實證明,R無論如何都不允許我在原始包裝環境中重新分配函數。不過,我一直在玩類似你的想法,將修改後的功能分配到新的環境中,並將新的環境附加到搜索路徑。 – user3474009

相關問題