[Rd] S4 classes and methods with optional arguments

Seth Falcon sfalcon at fhcrc.org
Tue Feb 14 17:22:04 CET 2006


Hi Josef,

On 14 Feb 2006, leydold at statistik.wu-wien.ac.at wrote:
> I have used a construct to allow optional arguments:
>
> if(!isGeneric("rstream.sample")) setGeneric("rstream.sample",
> function(stream,...) standardGeneric("rstream.sample"))

First, a question:
  Is this idiom of testing for the generic before defining it still
  "recommended"?  It seems to me that one should either define one's
  own generic in the package namespace or define a method for a
  *particular* generic defined elsewhere.  Otherwise, one could end up
  defining a method for the wrong generic.

> setMethod("rstream.sample", c("rstream","numeric"),
> function(stream,n=1) { ... [ code ] ... } )

This will work if you remove the second arg in the signature.  That
is,

  setMethod("rstream.sample", signature(stream="rstream"),
            function(strea, n=1) { ... })

Putting an arg in the signature means dispatching on that arg.  You
cannot dispatch on an arg that is not named in the definition of the
generic.

> however, with R-devel the above construct does not work any more,
> due to more stringent checkings. It can be fixed by replacing it by
>
> if(!isGeneric("rstream.sample")) setGeneric("rstream.sample",
> function(stream,n) standardGeneric("rstream.sample"))
>
> setMethod("rstream.sample", c("rstream","numeric"),
> function(stream,n=1) { ... [ code ] ... } )
>
> then rstream.sample(rs) does not work any more.
>
> Is there still a way to allow optional arguments for methods of S4
> classes?

Here's an approach that works for me:

1. You have to specify a default value to args *in the generic*.  This
   doesn't make a whole lot of sense to me, but it does seem to be
   needed.

   setGeneric("rstream.sample", 
              function(stream, n=0) standardGeneric("rstream.sample"))

2. Then define a method with a signature that matches the default
   case:

   setMethod("rstream.sample", signature(stream="rstream", n="missing"),
             function(stream, n=1) { ... })

   Note that you could also use signature(stream="rstream"), but then
   a call like rstream.sample(s, "foo") could match... Leaving out the
   arg is like saying n="ANY".

HTH,

+ seth



More information about the R-devel mailing list