Skip to content
Prev 33185 / 398506 Next

c(...) and methods

The "..." formal argument can't be used directly in a method signature.

The whole "..." mechanism is somewhat outside the regular S language. 
It can only be passed down in another call, and then the effect is a
macro-like substitution.  Unlike other formal arguments, "..." is not an
object in the usual sense, so defining methods based on its class would
not be meaningful.

There are some partial workarounds, but first we have to understand what
is really the intention.

In some functions (max(), for example), what happens is an operation on
one argument at a time, and then some combination of the results.  
There is a (more or less) OK workaround in this case--see page 351 of
"Programming with Data".

The case of c() is different.  What DO we want here?  Do the arguments
have to be of the same class?  Or do we claim  to combine a "collection"
object with anything else?  Probably not the second case, and hopefully
not also, since that one will be hard to manage.

Your example suggests that combining two collection objects is the main
goal.  For this, you need a function that takes two ordinary arguments,
and "..." to soak up others.

You _could_ redefine the function c() in this form, but a more cautious
approach is to define a new function, glue(), that behaves like c():

R> glue <- function(e1, e2, ...) c(e1, e2, ...)

We need to make this a generic function, define a method for two
collections, and also a method for a single argument:

R> setMethod("glue", signature(e2 = "missing"), function(e1, e2, ...)
e1)
[1] "glue"

R> setMethod("glue", signature(e1 = "collection", e2 = "collection"),
glueCollections)
[1] "glue"

(The function glueCollections is the function(e1, e2, ...) that was the
method in your mail.)

With this definition, any number of collections can be glue'd and remain
collections.  Glue-ing collections to anything else just invokes c() and
returns a list.

R> now <- Sys.time()
R> x <- new("collection", list(1, 2, 3), date = now)
R> y <- new("collection", list(4, 5, 6), date = now)

R> xy <- glue(x,y)
R> class(xy)
[1] "collection"
R> xyy <- glue(x,y,y)
R> class(xyy)
[1] "collection"
R> unlist(xy)
[1] 1 2 3 4 5 6
R> unlist(xyy)
[1] 1 2 3 4 5 6 4 5 6
R> xz <- glue(x, pi)
R> class(xz)
[1] "list"
R> unlist(xz)
[1] 1.000000 2.000000 3.000000 3.141593

The details will depend on what's wanted in a particular case, of
course, but the general idea is to re-think what's wanted in terms of
one or more ordinary arguments.  Not every example will work, but many
will.

John Chambers
"Marsland, John" wrote: