使用Roxygen2记录R6类方法

3

我正在编写一个带有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 RStudio, https://github.com/klutometis/roxygen/issues/306),但我认为这对于R6类来说并不支持。
如何最好地单独记录我的类方法?

我不使用 Roxygen2,但是也许以后可以添加方法,使用 Person$set("public", "set_hair", function(val) ...) 可以让你加入 Roxygen 注释。 - user2554330
刚试了一下,将函数和 Person$set 放在类声明下面的同一个文件中。不幸的是,这根本没有被渲染出来... - user1981275
在这种情况下,我会做两件事:1、手动编写.Rd文件;2、阅读https://github.com/klutometis/roxygen/issues/388,其中讨论了这样的问题。 - user2554330
2个回答

3

这是一篇旧的帖子,你可能很久以前就解决了你的问题。但它并没有被添加在这里,所以以防有人需要解决方案,它将是:

#' 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
  },
  )
)

2
在上面用户user2554330的评论中提到的与github相关的问题的讨论表明,将文档分离出来不是roxygen的待办事项,因为它不符合方法文档的传统样式。尽管如此,我仍然发现它很有用,并且一直在使用解决方法。
一个部分解决方案是创建功能性包装器。这是一个半手动的过程,如果有很多方法(就像你的情况),可能会很繁琐,但它确实可以为R6方法在单独的文档中提供清晰和半自动化的文档。以下是使用roxygen2实现可文档化包装器的示例,以person为例:
#` 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语法的设置方式。无需显式赋值,同时保持R6的优势并添加最小的开销,两者person$set_hair(val)和set_hair(person, val)将产生相同的结果。

编辑:

在与一些人讨论后,我发现更多的人更喜欢具有实际功能的表单包装器——这些包装器为了实现功能方法而牺牲了参考组件,因为它更接近于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()以保持一致性。 - Gregor de Cillia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接