The Use of
... in Method Signatures
Using "..." in a Signature
Beginning with version 2.8.0 of R, S4 methods can be dispatched
(selected and called) corresponding to the special argument
Given a suitable generic function, methods are specified in the
usual way by a call to
setMethod. The method
definition must be written expecting all the arguments corresponding
Typically the methods will pass
When you have a computation that is suitable for more than one existing
class, a convenient approach may be to define a union of these
classes by a call to
setClassUnion. See the example
Method Selection and Dispatch for "..."
See Methods for a general discussion. The following assumes
you have read the
A method selecting on
setMethod. If all the actual arguments
Otherwise, the class of each argument and that class' superclasses are
computed, beginning with the first
At the end of the iteration, one or more methods may be eligible.
If more than one, the selection looks for the method with the least
distance to the actual arguments. For each argument, any inherited
method corresponds to a distance, available from the
slot of the class definition. Since the same class can arise for
more than one argument, there may be several distances associated
with it. Combining them is inevitably arbitrary: the current
computation uses the minimum distance. Thus, for example, if a
method matched one argument directly, one as first generation
superclass and another as a second generation superclass, the
distances are 0, 1 and 2. The current selection computation would
use distance 0 for this
method. In particular, this selection criterion tends to use a method that
matches exactly one or more of the arguments' class.
As with ordinary method selection, there may be multiple methods with the same distance. A warning message is issued and one of the methods is chosen (the first encountered, which in this case is rather arbitrary).
Notice that, while the computation examines all arguments, the essential cost of dispatch goes up with the number of distinct classes among the arguments, likely to be much smaller than the number of arguments when the latter is large.
Methods dispatching on
setGeneric is inserted in the generic function's
environment. The local version selects a method according to the
criteria above and calls that method, from the environment of the
generic function. This is slightly different from the action taken
by the C implementation when
Methods dispatching on arguments other than
showMethods will expose such inherited methods.
The intention is that the
Chambers, John M. (2008) Software for Data Analysis: Programming with R Springer. (For the R version.)
Chambers, John M. (1998) Programming with Data Springer (For the original S4 version.)
For the general discussion of methods, see Methods and links from there.
cc <- function(...)c(...) setGeneric("cc") setMethod("cc", "character", function(...)paste(...)) setClassUnion("Number", c("numeric", "complex")) setMethod("cc", "Number", function(...) sum(...)) setClass("cdate", contains = "character", representation(date = "Date")) setClass("vdate", contains = "vector", representation(date = "Date")) cd1 <- new("cdate", "abcdef", date = Sys.Date()) cd2 <- new("vdate", "abcdef", date = Sys.Date()) stopifnot(identical(cc(letters, character(), cd1), paste(letters, character(), cd1))) # the "character" method stopifnot(identical(cc(letters, character(), cd2), c(letters, character(), cd2))) # the default, because "vdate" doesn't extend "character" stopifnot(identical(cc(1:10, 1+1i), sum(1:10, 1+1i))) # the "Number" method stopifnot(identical(cc(1:10, 1+1i, TRUE), c(1:10, 1+1i, TRUE))) # the default stopifnot(identical(cc(), c())) # no arguments implies the default method setGeneric("numMax", function(...)standardGeneric("numMax")) setMethod("numMax", "numeric", function(...)max(...)) # won't work for complex data setMethod("numMax", "Number", function(...) paste(...)) # should not be selected w/o complex args stopifnot(identical(numMax(1:10, pi, 1+1i), paste(1:10, pi, 1+1i))) stopifnot(identical(numMax(1:10, pi, 1), max(1:10, pi, 1))) try(numMax(1:10, pi, TRUE)) # should be an error: no default method ## A generic version of paste(), dispatching on the "..." argument: setGeneric("paste", signature = "...") setMethod("paste", "Number", function(..., sep, collapse) c(...)) stopifnot(identical(paste(1:10, pi, 1), c(1:10, pi, 1))) for(gen in c("numMax", "cc", "paste")) removeGeneric(gen) for(cl in c("Number", "vdate", "cdate")) removeClass(cl)