[R] c(...) and methods
John Chambers
jmc at research.bell-labs.com
Wed Jun 11 15:52:58 CEST 2003
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:
>
> I have been writing some S4 classes and have a problem about how I might
> pass a signature to "c()".
>
> Take the following example:
>
> setClass("collection", representation("list", date="POSIXt"))
>
> x <- new("collection", list(1,2,3), date=Sys.time())
> y <- new("collection", list(4,5,6), date=Sys.time())
>
> obviously, I can do c(x,y), but this wil be of class "list"
>
> I would like to do something like:
>
> setMethod("c", signature("collection"),
> function(...) {
> if(e1 at date!=e2 at date) stop("at different dates!")
> res <- c(as(e1, "list"),as(e2, "list"))
> new("collection", res, date = e1 at date)
> })
>
> but c() takes "..." as its arguments and I don't know how I might reference
> that with a signature and appropriate arguments etc.
>
> Has anybody an ideas? I presume it doesn't matter that c() is
> .Primative("c")?
>
> Regards,
>
> John Marsland
>
> **********************************************************************
> This is a commercial communication from Commerzbank AG.\ \ This ... {{dropped}}
>
> ______________________________________________
> R-help at stat.math.ethz.ch mailing list
> https://www.stat.math.ethz.ch/mailman/listinfo/r-help
--
John M. Chambers jmc at bell-labs.com
Bell Labs, Lucent Technologies office: (908)582-2681
700 Mountain Avenue, Room 2C-282 fax: (908)582-3340
Murray Hill, NJ 07974 web: http://www.cs.bell-labs.com/~jmc
More information about the R-help
mailing list