【问题标题】:How to export S3 method so it is available in namespace?如何导出 S3 方法使其在命名空间中可用?
【发布时间】:2013-09-01 23:31:41
【问题描述】:

我正在创建一个包,对于 S3 方法我使用导出它们

##' @method predict myclass
##' @export
predict.myclass <- function(object,...) { }

现在,当我加载包时,predict 会作用于 myclass 类的对象,但不会导出函数 predict.myclass。在 NAMESPACE 中,我只得到 S3method(predict,myclass) 条目。那么有没有办法把predict.myclass也导出来,让用户在控制台写predict.myclass时得到predict.myclass的代码?

【问题讨论】:

    标签: r devtools roxygen2


    【解决方案1】:

    如果您想在 NAMESPACE 中以自动方式在 roxygen2 中同时包含 S3method 和 export 指令,您只需添加一个更明确的额外 @export 标记。

    为了说明,我创建了一个虚拟包exportTest。这个包在R/子目录下只有一个文件print.foo.R:

    #' Print method for "foo" class
    #'
    #' @param x An object of class "foo"
    #' @param ... Other arguments passed to or from other methods
    #'
    #' @export print.foo
    #' @export
    print.foo <- function(x, ...) {
        cat("This is just a dummy function.\n")
    }
    

    document()ing 之后,我有以下NAMESPACE:

    # Generated by roxygen2: do not edit by hand
    
    S3method(print,foo)
    export(print.foo)
    

    我从Hadley's advice on exporting a non-S3-method function with a . in the name 得到这个想法。如果你使用

    #' @export function.name
    

    它通过提供的function.name 明确使用export() 指令。然后我测试了你是否可以将它与更模糊的@export 标记结合起来生成S3method() 指令,瞧!它有效。

    但是,我会注意到,据我所知,没有任何记录可以肯定地做到这一点,因此有可能在某个时候停止工作,甚至可能没有警告。如果这是您想要确保存在和/或已记录在某处的功能,我建议您使用opening an issue at their GitHub repo。

    【讨论】:

      【解决方案2】:

      我的回答是“不要那样做”。用户可以methods(predict); getAnywhere('predict.myclass') 或mypackage:::predict.myclass。用户有一个学习曲线,但使用您的方法掌握这一点有助于用户浏览所有方法。不导出该方法的原因是它不打算直接调用,并且它会用不必要的符号混淆搜索路径(在提示符下键入的每个符号,例如,ls(),必须通过查看对象来找到search() 返回的所有环境,以及像您这样的用户包都位于这些常用函数的搜索开始和名称解析之间)。

      【讨论】:

      • 好的,这是另一个问题stackoverflow.com/questions/18513607/…。我认为我可以通过额外的导出来解决我的问题。
      • 你确定吗? According to Hadley,每个 S3 方法都必须导出。也许我误解了你的回答。
      • @StéphaneLaurent OP 已经有S3method(predict, myclass),这是必要且充分的;也许这就是哈德利所说的“必须出口”。既没必要也不推荐export(predict.myclass)。
      • 谁说不推荐?如果不推荐,为什么要导出print.data.frame?
      • @January 我想我说不推荐? ;) print.data.frame 在基础包中定义,其中没有命名空间,因此没有不导出它的选项。
      【解决方案3】:

      对于那些迟到的人,在较新版本的 roxygen (=> 3.0) 中,@export 标签将自动工作如何处理方法。

      来自Generating Rd files 小插图:

      S3 泛型是常规函数,因此请照此记录它们。 S3 类没有正式定义,因此请记录构造函数。您可以选择是否记录 S3 方法。您不需要为简单的泛型(如 print())记录方法。如果您的方法更复杂,您应该记录它,以便人们知道参数的作用。在 base R 中,您可以找到更复杂方法的文档,例如 predict.lm()、predict.glm() 和 anova.glm()。

      旧版本的 roxygen 需要所有 S3 方法的显式 @method 通用类标签。从 3.0.0 开始不再需要,因为 roxygen2 会自动计算出来。如果您正在升级,请确保删除这些旧标签。仅当泛型和类不明确时,自动方法检测才会失败。例如 all.equal.data.frame() 是 all 的 equal.data.frame 方法,还是 all.equal 的 data.frame 方法?如果发生这种情况,您可以使用(例如)@method all.equal data.frame 来消除歧义。

      【讨论】:

        【解决方案4】:

        我完全同意在某些情况下导入 S3 方法是可取的,我不知道有任何权威来源声称不建议这样做。即使是base 包导出方法,如print.data.frame。

        也就是说,除了手动修改 NAMESPACE 文件并添加行之外,我还没有找到合理的 roxygen2 解决方案

        export(print.myClass)
        

        替代方法是复制函数:

         print_myClass <- function(x, ...) print.myClass(x, ...)
        

        这两种解决方案都有缺点。前者有手动编辑 NAMESPACE 的明显缺点,后者引入了混乱。

        【讨论】:

          猜你喜欢
          • 2018-08-25
          • 2021-02-26
          • 2015-03-17
          • 1970-01-01
          • 2014-11-02
          • 2016-12-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多