【问题标题】:Documenting R6 class methods with Roxygen2使用 Roxygen2 记录 R6 类方法
【发布时间】:2018-09-16 13:32:42
【问题描述】:

我正在编写一个包含多个方法的 R6 类的包。我希望能够为类和方法生成文档。对于下面的示例,我希望能够使用?Person 访问文档,使用?set_hair 访问方法。这是我的示例类:

#' This is my Person class
#' @title Person Class
#' @docType class
#' @description Person class description
#' @field name Name of the person
#' @field hair Hair colour
#'
#' @section Methods:
#' \describe{
#' \item{set_hair Set the hair color}
#' }
#' 
#' @examples
#' Person$new(name="Bill", hair="Blond")
#' @export
Person <- R6::R6Class("Person",
  public = list(
    name = NULL,
    hair = NULL,
    initialize = function(name = NA, hair = NA) {
      self$name <- name
      self$hair <- hair
  },    

    # '@name set_hair
    # '@param val: hair colour
    set_hair = function(val) {
      self$hair <- val
  },
  )
)

运行roxygenise(),方法体上面的注解根本不渲染,所以我在@section Methods中指定的唯一信息是在文档中。

由于我有超过 50 个类方法,如果我可以使用 ?methodname 单独访问方法文档会更好。我发现了一些关于此的帖子(Documenting R6 classes and methods within R package in RStudiohttps://github.com/klutometis/roxygen/issues/306),但在我看来,R6 类不支持此功能。

分别记录我的类方法的最佳方式是什么?

【问题讨论】:

  • 我不使用Roxygen2,但也许稍后使用Person$set("public", "set_hair", function(val) ...) 添加该方法将允许您放入Roxygen cmets。
  • 刚刚试了一下,把函数和Person$set放在同一个文件里类声明下面。不幸的是,这根本没有被渲染......
  • 在这种情况下,我会做两件事,1,只需手动编写一个 .Rd 文件,2,阅读 github.com/klutometis/roxygen/issues/388 讨论这样的内容。

标签: r documentation roxygen2 roxygen r6


【解决方案1】:

在上面 user2554330 的评论中链接的 github-raised issue 上的讨论表明,分离出的文档不在 roxygen 的待办事项列表中,因为它不符合方法文档的传统风格。也就是说,我仍然觉得它很有用,并且一直在使用解决方法。

一种部分解决方案是创建功能性包装器。这是一个半手动过程,给定许多方法(如您的情况)可能会很麻烦,但它确实在单独的文档中为 R6 方法启用了清晰和半自动化的文档。使用person 示例,这是在 roxygen2 中可能实现的可文档化包装器:

#` Method for setting hair
#` 
#` @param person a person class object
#` @param val hair color
#` 
#` @return nothing; modifies \code{person}
#` @export
#` 
#` @examples
#` bill <- Person$new(name="Bill", hair="Blond")
#` bill$set_hair("InspiredRed")
#` bill$hair
#` set_hair(bill, "MetalBlack")
#` bill$hair
set_hair <- function(person, val){
  person$set_hair(val)
  invisible()
}

结果将是两个独立的.Rd 文件,一个用于person 类,一个用于set_hair 方法,都可以通过? 访问。

结果还有一个额外的优势,那就是大多数 R 用户可能更喜欢更接近函数形式的调用,因为这更接近大多数 R 语法的设置方式。 person$set_hair(val)set_hair(person, val) 都将产生相同的结果,无需任何显式分配,保持 R6 的优势,同时增加最小的开销。


编辑:

在向几个人提出这个问题后,我发现我更喜欢使用实际的函数式表单包装器——因为它更接近 R 的“规范”,所以它牺牲了引用组件以支持函数式方法。在这种情况下,该方法仍然提供相同的文档优势,而引用方法调用仍然可以通过$ 获得。但是,在编写包装文档时,应额外强调引用方法方法的存在。

#` Clones person and changes hair
#` 
#` @param person a person class object
#` @param val hair color
#` 
#` @return nothing; modifies \code{person}
#` @export
#` 
#` @details This creates a new person with the same characteristics as the \code{person}
#' provided, except with new hair. To update the original person's hair by reference,
#' use \code{person$set_hair()}.
#` 
#` @examples
#` bill <- Person$new(name="Bill", hair="Blond")
#` bill$set_hair("InspiredRed")
#` bill$hair
#` set_hair(bill, "MetalBlack")
#` bill$hair
set_hair <- function(person, val){
  personNew <- person.clone()
  personNew$set_hair(val)
  invisible(personNew) # invisible assuming no print method, but you probably want one
}

当然,使用这些包装器采用哪种路径取决于您的特定应用程序的速度和内存要求。功能性方法可能会造成足够的障碍,使其不可行。

【讨论】:

  • 出于一致性原因,我认为您的第二个示例应为 person_clone()person$clone()
【解决方案2】:

这是一篇旧帖子,您可能早就解决了您的问题。但是这里没有添加,所以如果有人需要解决方案,它将是:

#' This is my Person class
#' @description Person class description
#' @field name Name of the person
#' @field hair Hair colour
#' 
#' @examples
#' Person$new(name="Bill", hair="Blond")
#' @export
Person <- R6::R6Class("Person",
  public = list(
    name = NULL,
    hair = NULL,

    #' @description
    #' Create a person
    #' @param name Name of the person
    #' @param hair Hair colour
    initialize = function(name = NA, hair = NA) {
      self$name <- name
      self$hair <- hair
  },    

    #' @description Set hair
    #' @param val Hair colour
    set_hair = function(val) {
      self$hair <- val
  },
  )
)

【讨论】:

    猜你喜欢
    • 2011-11-13
    • 2018-01-07
    • 1970-01-01
    • 1970-01-01
    • 2011-11-04
    • 2014-08-06
    • 2022-12-14
    • 2011-11-14
    • 2012-03-22
    相关资源
    最近更新 更多