语言是R。
我有几个文件:
utilities.non.foo.R
utilities.foo.R
utilities.R
foo
是一个拼凑在一起的内部包(用于图像处理,虽然这是无关紧要的)。它工作得很好,但只能在Linux机器上运行,即使在这些机器上尝试编译它也是一件非常大的痛苦。
基本上,utilities.foo.R
包含许多需要包foo
的函数。
这里的函数称为functionname.foo
。
我即将开始与没有此软件包或Linux的外部协作者共享此代码,因此我编写了一个文件utilities.non.foo.R
,其中包含utilities.foo.R
中的所有函数,除了已删除对包foo
的依赖。
这些函数都称为functionname.non.foo
。
对于每个函数,文件utilities.R
都有一整堆:
functionname <- function(...) {
if ( fooIsLoaded() ) {
functionname.foo(...)
} else {
functionname.non.foo(...)
}
}
我们的想法是只需要加载utilities.R
,如果您碰巧拥有包foo
(例如我的内部协作者),您将使用该后端。如果您不拥有foo
(外部协作者),则您将使用非foo后端。
我的问题是:是否有一些方法可以为每个函数名重定向,而无需为每个函数名显式编写上面的代码?
这让我想起(例如)有print
方法,print.table
,print.data.frame
等,但用户只需要使用print
使用的方法是自动选择的。
除了method.class
更像method.depends_on_which_package_is_loaded
之外,我想要那样做。
有没有办法避免在我的utilities.R
文件中为每个函数编写重定向函数?
答案 0 :(得分:2)
正如Dirk所说,只需使用一个包裹。在这种情况下,将所有新的*.non.foo
函数放在一个新的包中,该包也称为foo
。将此foo
分发给您的协作者,而不是您的内部版本。这样你的实用程序代码可以只是
functionname <- function(...) functionname.foo(...)
无需进行任何检查。
答案 1 :(得分:1)
这是一个想法:编写一个将f
设置为f.foo
或f.non.foo
的函数。它可以在循环中调用,在给定命名空间中的所有函数(或名称以.foo
结尾的所有函数)中调用。
dispatch <- function(s) {
if ( fooIsLoaded() ) {
f <- get( paste(s, "foo", sep=".") )
} else {
f <- get( paste(s, "non.foo", sep=".") )
}
assign( s, f, envir=.GlobalEnv ) # You may want to use a namespace
}
f.foo <- function() cat("foo\n")
f.non.foo <- function() cat("non-foo\n")
fooIsLoaded <- function() TRUE
dispatch("f")
f()
fooIsLoaded <- function() FALSE
dispatch("f")
f()
更简单的解决方案是提供相同的名称 两个函数,但将它们放在不同的命名空间/包中。
答案 2 :(得分:0)
这听起来非常低效且不优雅,但是怎么样
funify = function(f, g, package="ggplot2") {
if(paste("package:", package, sep="") %in% search()) f else
{ message("how do you intend to work without ", package) ; g}
}
detach(package:ggplot2)
foo = funify(paste, function(x) letters[x])
foo(1:10)
library(ggplot2)
foo = funify(paste, function(x) letters[x])
foo(1:10)