13

我目前正在研究 R 包,并尝试遵循 Hadley Wickham 在http://r-pkgs.had.co.nz提供的最佳实践指南。作为其中的一部分,我的目标是将所有包依赖项都放在说明文件的 Imports 部分而不是 Depends 中,因为我同意不要不必要地改变全局环境的理念(许多 CRAN 和 Bioconductor 包不这样做'似乎没有跟随)。

我想在我的一个包函数中使用 Bioconductor 包 rhdf5 中的函数,特别是h5write(). 我现在遇到的问题是它没有在其 NAMESPACE 中声明其 S3 方法。它们是使用(例如)声明的

export(h5write.default)
export(h5writeDataset.matrix)

而不是

S3method(h5write, default)
S3method(h5writeDataset, matrix)

通用 h5write 定义为:

h5write <- function(obj, file, name, ...) {
res <- UseMethod("h5write")
  invisible(res)
}

实际上,这意味着调用 rhdf5::h5write 失败,因为没有注册适当的 h5write 方法。

据我所知,解决方案有以下三种:

  1. 使用Depends而不是Imports在说明文件中。
  2. 在相关功能的代码中使用library("rhdf5")require("rhdf5")
  3. 修改 rhdf5 的 NAMESPACE 文件以使用S3methods()而不是export().

所有这些都有缺点。选项 1 意味着即使我的包中的相关函数从未被调用,该包也已加载并附加到全局环境。选项 2 表示library在包中使用,同时又将包附加到全局环境,并且根据 Hadley Wickham 的指南也已弃用。选项 3 意味着依赖其他包作者在 Bioconductor 上更新他们的包,也意味着不再导出 S3 方法,这反过来可能会破坏其他依赖显式调用它们的包。

我错过了另一种选择吗?我在 StackOverflow 上查看了其他地方,发现了以下一些相关的问题Importing S3 method from another packageHow to export S3 method so it is available in namespace? 但没有任何东西可以直接解决我的问题。值得注意的是,与这两者中的第一个的主要区别在于泛型和方法都在同一个包中,但问题是使用export而不是S3method.

重现错误的示例代码(无需创建包):

loadNamespace("rhdf5")
rdhf5::h5write(1:4, "test.h5", "test")

Error in UseMethod("h5write") : 
no applicable method for 'h5write' applied to an object of class
"c('integer', 'numeric')

或者,在https://github.com/NikNakk/s3issuedemo有一个骨架包,它提供了一个demonstrateIssue()重现错误消息的函数。它可以使用devtools::install_github("NikNakk/s3issuedemo").

4

1 回答 1

10

这里的关键是除了要使用的泛型之外,还要导入特定的方法。以下是如何使它适用于默认方法。

注意:这假设test.h5文件已经存在。

#' @importFrom rhdf5 h5write.default
#' @importFrom rhdf5 h5write
#' @export
myFun <- function(){
    h5write(1:4, "test.h5", "test")
}

我也在这里放了我自己的小包装来展示这一点

于 2015-06-11T13:47:01.980 回答