2014-02-20 32 views
3

我目前正在開發兩個包,下面是一個簡化 版本我的問題:R包開發:從一個包中重寫一個函數與另一個函數?

在包AI有一些功能(說「sum_twice」),我也呼籲 包內的另一個功能(說「slow_sum」)。 然而,在包B,我寫了另一個函數(比如「fast_sum」),與 我希望在包A.替換速度慢功能現在

,如何管理這個「slow_sum的「覆蓋」 「功能與 」fast_sum「功能?

下面是這些功能的一個簡單的例子(只是爲了說明):

############################ 

############## 
# Functions in package A 

slow_sum <- function(x) { 
sum_x <- 0 
for(i in seq_along(x)) sum_x <- sum_x + x[i] 
sum_x 
} 

sum_twice <- function(x) { 
x2 <- rep(x,2) 
slow_sum(x2) 
} 

############## 
# A function in package B 
fast_sum <- function(x) { sum(x) } 

############################ 

如果我只有這樣做slow_sum <- fast_sum,這是行不通的,因爲「sum_twice」使用「slow_sum」從命名空間 包A的

予加載包 「B」 時,使用下面的函數嘗試:

assignInNamespace(x = "slow_sum", value = B:::fast_sum, ns = "A") 

這indee d工作,但是,它使得CRAN檢查同時返回 的NOTE,我不應該使用「:::」,並且還會使用assignInNamespace (因爲它應該不是很安全)。

但是,我不知所措。 有什麼辦法讓「sum_twice」使用「fast_sum」而不是 「slow_sum」?

感謝您前期的任何意見或建議, 與問候, 塔爾

PS:這是一個雙崗from here.

UDPATE:動機這個問題

我正在開發兩個軟件包,一個完全基於R,工作正常(但有點慢),它是dendextend(現在在CRAN上)。另一個是通過使用Rcpp來加速第一個包(這是在github上的dendextendRcpp)。第二個包通過覆蓋第一個包使用的一些基本功能來加速第一個包。但爲了讓第一個包中的高級函數能夠使用第二個包中的低級函數,我必須使用assignInNamespace,它會導致CRAN拋出警告+ NOTES,這會導致包被CRAN拒絕(直到這些警告將會避免)。

問題是我不知道如何解決這個問題。我能想到的唯一解決方案是將兩個軟件包混合在一起(使其更難維護,並且會自動需要更大的依賴性結構以供請求使用軟件包的人員使用)。另一個選擇是將dendextend中的更高級別的功能粘貼到dendextendRcpp,從而使其隱藏其他功能。但是我覺得這樣做不那麼優雅(因爲這意味着我需要複製粘貼許多功能,強制更多的雙代碼維護)。任何其他想法?謝謝。

+1

即使你找到一個方法來做到這一點,CRAN會返回某種警告或錯誤:否則您的軟件包將能夠更改任何其他已加載軟件包的底層功能。 –

+0

你爲什麼想要這樣做? – hadley

+0

哈德利 - 我已經更新了動機的問題。謝謝你看看。 –

回答

1

我結束了使用(感謝烏韋和庫爾特)解決方案,採用「本地」創建與封裝選項的局部環境。如果你好奇,該功能被稱爲「dendextend_options」,並且是在這裏: https://github.com/talgalili/dendextend/blob/master/R/zzz.r

下面是其使用的例子:

dendextend_options <- local({ 
    options <- list() 
    function(option, value) { 
     #   ellipsis <- list(...)   
     if(missing(option)) return(options) 

     if(missing(value)) 
     options[[option]] 
     else options[[option]] <<- value 
    } 
}) 
dendextend_options("a") 
dendextend_options("a", 1) 
dendextend_options("a") 
dendextend_options("a", NULL) 
dendextend_options("a") 
dendextend_options() 
2

我們可以把這個sum_twice

my_sum_ch <- getOption("my_sum", if ("package:fastpkg" %in% search()) 
         "fast_sum" else "slow_sum") 
my_sum <- match.fun(my_sum_ch) 

如果"my_sum"選項進行設置,那麼的my_sum該版本將被使用,如果沒有它將使基於與否fastpkg的決定已經被加載。

相關問題