我目前正在开发两个软件包,下面是一个简化版 我的问题的版本:
在包A中,我有一些函数(比如“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”使用来自NAMESPACE的“slow_sum”
包A。
我在加载包“B”时尝试使用以下函数:
assignInNamespace(x = "slow_sum", value = B:::fast_sum, ns = "A")
这确实有效,但是,它使CRAN检查返回两个注释 我不应该使用“:::”,还有使用assignInNamespace的警告 (因为它应该不是很安全)。
然而,我不知所措。 什么是让“sum_twice”使用“fast_sum”代替的方法 “slow_sum”?
先感谢您的任何反馈或建议, 带着敬意, 塔尔
p.s:这是一篇双重帖from here.
UDPATE:此问题的动机
我正在开发两个包,一个完全基于R并且工作正常(但有点慢),它是dendextend(现在在CRAN上)。另一个是通过使用Rcpp来加速第一个包(这是dendextendRcpp,它位于github上)。第二个包通过覆盖第一个包使用的一些基本功能来加速第一个包。但是为了第一个包中的更高级别的函数将使用第二个包中的较低函数,我必须使用assignInNamespace导致CRAN抛出警告+ NOTES,最终导致CRAN拒绝包(直到这些警告将避免)。
问题在于我不知道如何处理这个问题。我能想到的唯一解决方案是将两个包混合在一起(使其更难维护,并且对于要求使用该包的人自动需要更大的依赖结构)。另一种选择是只复制将更高级别的函数从dendextend复制到dendextendRcpp,从而让它们掩盖其他函数。但我觉得这不那么优雅(因为这意味着我需要复制粘贴许多功能,强制进行更多的双重代码维护)。还有其他想法吗?感谢。
答案 0 :(得分: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来做出决定。
答案 1 :(得分:1)
我最终使用的解决方案(感谢Uwe和Kurt)正在使用&#34; local&#34;使用包选项创建本地化环境。如果你很好奇,这个函数被称为&#34; dendextend_options&#34;,并且在这里: 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()