-
-
Notifications
You must be signed in to change notification settings - Fork 86
Roxygen R6 Guide
This guide shows how to document R6
objects using roxygen2
.
In case of differences within different packages regarding style, always stick with the style of the mlr3
core package.
The following examples use the Param
class of the paradox
package.
Start with the @title
, followed by the @description
(note that @usage
and @format
tags are not needed):
#' @title Param Object
#'
#' @description
#' Abstract base class for parameters.
After the @description
you should put the S3 methods
section, and the @include
, @family
, @export
and @example
parts (if applicable).
All other parts of the documentation (i.e., Construction
, Fields
, Active Bindings
, Methods
) will be moved directly above the matching R
code as done in the following sections.
Note that each parameter (@param
) must be specified via its <name>
(e.g., special_vals
) followed by its (<type>)
in parentheses (e.g., (`list()`)
, or ([Param])
). Then break the line using \cr
followed by two spaces indentation and the description of this parameter (e.g., Arbitrary special values this parameter is allowed to take, to make it...
):
Param = R6Class("Param",
public = list(
...
#' @description
#' Creates a new instance of this [R6][R6::R6Class] class.
#'
#' Note that this object is typically constructed via derived classes,
#' e.g., [ParamDbl].
#'
#' @param id (`character(1)`)\cr
#' Identifier of the object.
#' @param special_vals (`list()`)\cr
#' Arbitrary special values this parameter is allowed to take, to make it
#' feasible. This allows extending the domain of the parameter. Note that
#' these values are only used in feasibility checks, neither in generating
#' designs nor sampling.
#' @param default (`any`)\cr
#' Default value. Can be from the domain of the parameter or an element of
#' `special_vals`. Has value [NO_DEF] if no default exists. `NULL` can be a
#' valid default.
#' @param tags (`character()`)\cr
#' Arbitrary tags to group and subset parameters. Some tags serve a special
#' purpose:\cr
#' * `"required"` implies that the parameters has to be given when setting
#' `values` in [ParamSet].
initialize = function(id, special_vals, default, tags) {
...
},
...
),
...
Fields and Active Bindings are documented directly above the matching R
code resulting in them being differentiated automatically.
You may stumble across the case that you have to document a Field that was set during construction and the documentation of this Field would be identical to documentation of the parameter of the construction. To prevent too much redundancy here, keep the description of such Fields short (and document everything important within the documentation of the parameter of the construction). Each Field must again be specified via its <name>
(e.g., special_vals
) followed by the (<type>)
in parentheses (e.g., (`list()`)
). Then break the line using \cr
followed by a description (no indentation here) of this Field (e.g., Arbitrary special values this parameter is allowed to take.
):
Param = R6Class("Param",
public = list(
#' @field id (`character(1)`)\cr
#' Identifier of the object.
id = NULL,
#' @field special_vals (`list()`)\cr
#' Arbitrary special values this parameter is allowed to take.
special_vals = NULL,
#' @field default (`any`)\cr
#' Default value.
default = NULL,
#' @field tags (`character()`)\cr
#' Arbitrary tags to group and subset parameters.
tags = NULL,
...
),
...
The same documentation style holds for Active Bindings:
...
active = list(
#' @field class (`character(1)`)\cr
#' R6 class name. Read-only.
class = function() class(self)[[1L]],
#' @field is_number (`logical(1)`)\cr
#' `TRUE` if the parameter is of type `"dbl"` or `"int"`.
is_number = function() self$class %in% c("ParamDbl", "ParamInt"),
#' @field is_categ (`logical(1)`)\cr
#' `TRUE` if the parameter is of type `"fct"` or `"lgl"`.
is_categ = function() self$class %in% c("ParamFct", "ParamLgl"),
#' @field has_default (`logical(1)`)\cr
#' Is there a default value?
has_default = function() !is_nodefault(self$default),
#' @field storage_type (`character(1)`)\cr
#' Data type when values of this parameter are stored in a data table or sampled.
...
),
...
Methods need to document all their parameters (same style as for the construction, @param <name> (<type>)
) and their return value (@return <return_value>
), e.g., for the Param
's rep
method:
Param = R6Class("Param",
public = list(
...
#' @description
#' Repeats this parameter n-times (by cloning).
#' Each parameter is named "\[id\]_rep_\[k\]" and gets the additional tag "\[id\]_rep".
#'
#' @param n (`integer(1)`).
#' @return [ParamSet].
rep = function(n) {
...
}
...
),
...
-
Private Fields and Methods cannot be documented with
roxygen2
but it is good practice to follow the same style for internal documentation. -
If you find yourself reusing the same documentation parts a lot (e.g., for the
id
), useroxygen2
templates that go into theman-roxygen
directory of the package (make sure to ignore this directory when building the package, i.e., via.Rbuildignore
). Templates can be directly included in the documentation via@template <name_of_template>
(see e.g. the templates of theparadox
package for some reference). -
Make sure that
@param
and@field
sections (and of course all other sections, but there it is more obvious) end with a punctuation mark. -
When documenting types, make sure that they are put in between two grave accents (
`
), e.g.,(`numeric(1)`)
. This does not apply to objects that are part of packages, e.g.,([Param])
, which are instead put in between two square brackets. -
Don't forget to include the following line in the
DESCRIPTION
of the package:Roxygen: list(markdown = TRUE, r6 = TRUE)
.
CI
Roxygen (Documentation)
Style
Misc