[Bioc-devel] problem with documentation of setMethod with different signatures

Martin Morgan mtmorg@n@b|oc @end|ng |rom gm@||@com
Thu Feb 14 12:07:00 CET 2019


It's important to distinguish between problems in your code and problems in the tools (or use of tools) to process the code. Here the use of setGeneric() / setMethod() is correct. Your use of roxygen2 is getting in the way.

You've used @rdname to document the methods on the same page (reducing the number of man pages probably helps the user, so this is good). But then on the same page you've documented `@param x`, for instance, twice, once for GRanges and once for integer. Here the solution is to document `@param x` in only one place, e.g., in the generic, with sentences that describe appropriate input for each method.

#' @param x A `GRanges` instance or `integer` vector that...

For other tags, e.g., `@details`, `@return`, multiple uses are concatenated into paragraphs in a single element in the Rd file; one might then say

#' @details methodA,GRanges-method does one thing.
...
#' @details methodA,integer-method does another.

Generally, it is much harder to provide clear user-oriented documentation for S4 classes and methods, and roxygen requires a lot of manual effort to arrive at a satisfactory solution. You've already started down that road by using the @rdname tag to group methods documentation on the same page.

While open for discussion and certainly dependent on context, I think it is more helpful to group documentation by class rather than generic, e.g, 'I have a GRanges object, what can I do with it?' rather than 'I wonder what I can find the `start()` of?'. Also the best documentation pages are really very carefully constructed, and these are very difficult to generate automatically from roxygen snippets associated with individual functions / methods; an approach might be to provide a single roxygen chunk at the top of a source file that documents the content of the source file, with individual methods etc restricted to tags `@rdname` and `@export`. The old school approach is to simply edit the man page by hand directly.

Finally, it has proven very helpful to organize code, man pages, and unit tests in a parallel fashion

   R/My-class.R
  man/My-class.Rd
  tests/testthat/test_My-class.R

The GenomicRanges package https://github.com/Bioconductor/GenomicRanges might be an advanced example of structure, though based on old-school manual construction of Rd files.

Martin

On 2/14/19, 4:08 AM, "Bioc-devel on behalf of web working" <bioc-devel-bounces using r-project.org on behalf of webworking using posteo.de> wrote:

    Hi,
    
    I am struggling a bit with a R generic function. I build a generic and 
    set two implementations of the generic with two different signatures as 
    input. Both implementations of the generic produce the same output but 
    have a different input. During devtools::check() I get the following error:
    
    ❯ checking Rd \usage sections ... WARNING
       Duplicated \argument entries in documentation object 'methodA':
         ‘x’ ‘size’
    
      Functions with \usage entries need to have the appropriate \alias
       entries, and all their arguments documented.
       The \usage entries must correspond to syntactically valid R code.
       See chapter ‘Writing R documentation files’ in the ‘Writing R
       Extensions’ manual.
    
    
    The original functions are complex so here are some dummy methods:
    
    
    #' methodA methods generic
    #' @rdname methodA-methods
    #' @export
    #'
    setGeneric("methodA", function(x, size = 1000)
       standardGeneric("methodA"))
    
    
    #' methodA method for \code{GRanges} input
    #'
    #' @param x a \code{GRanges} object
    #' @param size a \code{numeric} vector
    #'
    #' @import GenomicRanges
    #' @return a \code{list} object
    #' @rdname methodA-methods
    #' @export
    #' @examples
    #' library(GenomicRanges)
    #' dat.GRanges <- GRanges(seqnames=c(rep("chr1", 5), rep("chr2", 5)),
    #' IRanges(start = rep(c(10000, 10000, 55000, 55000, 150000), 2),
    #' end = rep(c(20000, 20000, 70000, 70000, 600000), 2)))
    #' out.list <- methodA(x = dat.GRanges, size = length(dat.GRanges))
    #'
    setMethod(methodA, signature(x="GRanges"),
               function(x, size = 1000){
                 s <- start(x)
                 return(list(s, size))
               })
    
    
    
    #' methodA method for named \code{integer} input
    #'
    #' @param x a \code{integer} vector
    #' @param size a \code{numeric} vector
    #'
    #' @return a \code{list} object
    #' @export
    #' @rdname methodA-methods
    #' @examples
    #' dat <- 1:20
    #' out.list <- methodA(x = dat, size = length(dat))
    setMethod(methodA, signature(x="integer"),
               function(x, size = 1000){
                 return(list(x, size))
               })
    
    The error above sounds absolute understandable for me, but I do not have 
    a solution for this. Maybe using a generic is not the way to do this here?
    
    Tobias
    
    _______________________________________________
    Bioc-devel using r-project.org mailing list
    https://stat.ethz.ch/mailman/listinfo/bioc-devel
    


More information about the Bioc-devel mailing list