I am trying to understand this R CMD check warning for S3 function.
So, here is a completely reproducible example of my situation including R code and roxygen code. (I can never find a complete example of S3 anywhere and real-world usage in packages are either overly complicated or poorly documented. So, hopefully this is helpful to others implementing S3.)
#' @title An S3 generic.
#' @description An S3 generic that does something.
#' @param obj A numeric or character class object..
#' @param ... Other parameters are passed to methods.
#' @return Does something.
#' @export
#'
do_something <- function(obj, ...) {
if(!class(obj) %in% c("numeric","character")) stop("obj must be character or numeric class.")
UseMethod("do_something",obj)
}
#' @title An S3 method for obj class numeric.
#' @description An S3 method for obj class numeric.
#' @param obj A numeric class.
#' @param summary A character string.
#' @return Returns something.
#' @method do_something numeric
#' @rdname do_something.numeric
#' @importFrom stats median
#' @export
#'
do_something.numeric <- function(obj, summary="mean") {
if(summary=="mean") x <- mean(obj)
if(summary=="median") x <- median(obj)
return(x)
}
#' @title An S3 method for obj class character.
#' @description An S3 method for obj class character.
#' @param obj A character class.
#' @param collapse A character string.
#' @return Returns something.
#' @method do_something character
#' @rdname do_something.character
#' @export
#'
do_something.character <- function(obj, collapse=",") {
return(paste(obj,collapse=collapse))
}
I have an S3 generic do_something()
that dispaches to method functions do_something.numeric()
or do_something.character()
based on the obj
class. There are two method functions for the two different classes. And apart from the common shared argument obj
, they have distinct arguments themselves.
The functions work as intended, but running R CMD check on this returns this.
> checking S3 generic/method consistency ... WARNING
do_something:
function(obj, ...)
do_something.character:
function(obj, collapse)
do_something:
function(obj, ...)
do_something.numeric:
function(obj, summary)
See section ‘Generic functions and methods’ in the ‘Writing R
Extensions’ manual.
0 errors ✓ | 1 warning x | 0 notes ✓
Error: R CMD check found WARNINGs
Execution halted
Exited with status 1.
Now, I can fix this warning by adding , ...
to method functions as well as the roxygen part. Here is the fixed code.
#' @title An S3 generic.
#' @description An S3 generic that does something.
#' @param obj A numeric or character class object..
#' @param ... Other parameters are passed to methods.
#' @return Does something.
#' @export
#'
do_something <- function(obj, ...) {
if(!class(obj) %in% c("numeric","character")) stop("obj must be character or numeric class.")
UseMethod("do_something",obj)
}
#' @title An S3 method for obj class numeric.
#' @description An S3 method for obj class numeric.
#' @param obj A numeric class.
#' @param summary A character string.
#' @param ... Other parameters
#' @return Returns something.
#' @method do_something numeric
#' @rdname do_something.numeric
#' @importFrom stats median
#' @export
#'
do_something.numeric <- function(obj, summary="mean", ...) {
if(summary=="mean") x <- mean(obj)
if(summary=="median") x <- median(obj)
return(x)
}
#' @title An S3 method for obj class character.
#' @description An S3 method for obj class character.
#' @param obj A character class.
#' @param collapse A character string.
#' @param ... Other parameters
#' @return Returns something.
#' @method do_something character
#' @rdname do_something.character
#' @export
#'
do_something.character <- function(obj, collapse=",", ...) {
return(paste(obj,collapse=collapse))
}
But, why!!??
To my understanding, the ...
in the generic is meant to signify additional arguments being passed to any of the method functions. In this case, ...
stands for arguments summary
and/or collapse
. And adding ...
makes sense to me if I had another internal function inside my method function like this.
do_something.character <- function(obj, collapse=",", ...) {
x <- an_internal_function(obj=obj, collapse=collapse, ...)
return(x)
}
But, I have no additional arguments to pass, so why do I need the ...
and what does it do here? Hopefully someone can clarify this.
R_4.0.0