dotsMethods package:methods R Documentation _T_h_e _U_s_e _o_f "..." _i_n _M_e_t_h_o_d _S_i_g_n_a_t_u_r_e_s _D_e_s_c_r_i_p_t_i_o_n: The "..." argument in R functions is treated specially, in that it matches zero, one or more actual arguments (and so, objects). A mechanism has been added to R to allow "..." as the signature of a generic function. Methods defined for such functions will be selected and called when _all_ the arguments matching "..." are from the specified class or from some subclass of that class. _U_s_i_n_g "..." _i_n _a _S_i_g_n_a_t_u_r_e: Beginning with version 2.8.0 of R, S4 methods can be dispatched (selected and called) corresponding to the special argument "...". Currently, "..." cannot be mixed with other formal arguments: either the signature of the generic function is "..." only, or it does not contain "...". (This restriction may be lifted in a future version.) 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 to "..." to be from the class specified in the method's signature, or from a class that extends that class (i.e., a subclass of that class). Typically the methods will pass "..." down to another function or will create a list of the arguments and iterate over that. See the examples below. 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 below. _M_e_t_h_o_d _S_e_l_e_c_t_i_o_n _a_n_d _D_i_s_p_a_t_c_h _f_o_r "...": See Methods for a general discussion. The following assumes you have read the "Method Selection and Dispatch" section of that documentation. A method selecting on "..." is specified by a single class in the call to 'setMethod'. If all the actual arguments corresponding to "..." have this class, the corresponding method is selected directly. Otherwise, the class of each argument and that class' superclasses are computed, beginning with the first "..." argument. For the first argument, eligible methods are those for any of the classes. For each succeeding argument that introduces a class not considered previously, the eligible methods are further restricted to those matching the argument's class or superclasses. If no further eligible classes exist, the iteration breaks out and the default method, if any, is selected. 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 'contains' 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. _I_m_p_l_e_m_e_n_t_a_t_i_o_n _D_e_t_a_i_l_s: Methods dispatching on "..." were introduced in version 2.8.0 of R. The initial implementation of the corresponding selection and dispatch is in an R function, for flexibility while the new mechanism is being studied. In this implementation, a local version of '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 "..." is not involved. Aside from the extra computing time required, the method is evaluated in a true function call, as opposed to the special context constructed by the C version (which cannot be exactly replicated in R code.) However, situations in which different computational results would be obtained have not been encountered so far, and seem very unlikely. Methods dispatching on arguments other than "..." are _cached_ by storing the inherited method in the table of all methods, where it will be found on the next selection with the same combination of classes in the actual arguments (but not used for inheritance searches). Methods based on "..." are also cached, but not found quite as immediately. As noted, the selected method depends only on the set of classes that occur in the "..." arguments. Each of these classes can appear one or more times, so many combinations of actual argument classes will give rise to the same effective signature. The selection computation first computes and sorts the distinct classes encountered. This gives a label that will be cached in the table of all methods, avoiding any further search for inherited classes after the first occurrence. A call to 'showMethods' will expose such inherited methods. The intention is that the "..." features will be added to the standard C code when enough experience with them has been obtained. It is possible that at the same time, combinations of "..." with other arguments in signatures may be supported. _R_e_f_e_r_e_n_c_e_s: 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.) _S_e_e _A_l_s_o: For the general discussion of methods, see Methods and links from there. _E_x_a_m_p_l_e_s: 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)))