[Rd] Questions about S4 style methods and generics

John Chambers jmc@research.bell-labs.com
Thu, 09 May 2002 09:47:03 -0400


Saikat DebRoy wrote:
> 
> I have some questions about S4 style methods and generics.
> 
> First of all, is there any way of using default values for arguments
> in the generics/methods? My own experiments show that such arguments
> are always ignored.

Yes there is and no they are not.

But there are a couple of points to keep in mind.

The definition of method dispatch is that the _body_ of the selected
method is evaluated, without rematching arguments.  That means that it's
the default values in the (generic) function definition that will be
found in the context of the call.

An example:

R> bar <- function(x, y = 0)x+y
R> setGeneric("bar")
R> bar
function (x, y = 0) 
standardGeneric("bar")
<environment: 0x8622a18>
R> setMethod("bar", "character", function(x, y) paste(x,y))
[1] "bar"
R> bar(1,2)
[1] 3
R> bar(99)
[1] 99
R> bar("test")
[1] "test 0"

OTOH, the default expressions for the arguments in the method are
available in the method object.  You can extract them by getting the
method and retrieving, for example, def$y.  It seems a sufficiently
asked-for item that we'll provide a tool for it.

Maybe
  evaluateMethodDefault("y")
??  The point is to allow access but not burden the standard method
dispatch with re-matching arguments.

> The green book seems to be silent on this
> matter.
> 
> The second question is about using a non-trivial function body for
> generics. Page 351 of the green book gives an example of this and the
> documentation for setGeneric seems to suggest I should be able to do
> this at least by using myDispatch=TRUE. However, the current
> implementation seems to set the body of the generic definition to a
> call to standardGeneric all the time. Is this a bug or a modification
> of the green book description?

It's a bug.  Having said that, though, nonstandard generic functions are
slightly deprecated.  There are some potential efficiency enhancements
for dispatch that might be introduced but that would likely depend on
the function being a standard generic.

Also, experience is that people get a little confused and sometimes
provide a definition of the generic that doesn't call
standardGeneric("foo") and so does not give them the method dispatch
they expected.

But it's a bug & will be fixed.  Meanwhile, there is a workaround, if
you're willing to be a bit klunky.  You define the generic and then
replace the body, being careful to preserve the function's environment.

Another example:

R> foo <- function(x) x
R> setGeneric("foo")
[1] "foo"
R> body(foo, envir = environment(foo)) <- 
+ quote({cat("Here we go!\n"); standardGeneric("foo")})
R> setMethod("foo", "numeric", function(x)sum(x))
[1] "foo"
R> foo(1:10)
Here we go!
[1] 55
R> foo("test")
Here we go!
[1] "test"

> 
> Thanks,
> 
> Saikat
> --
> Department of Statistics                       Email: saikat@stat.wisc.edu
> University of Wisconsin - Madison              Phone: (608) 263 5948
> 1210 West Dayton Street                        Fax:   (608) 262 0032
> Madison, WI 53706-1685
> -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
> r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
> Send "info", "help", or "[un]subscribe"
> (in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
> _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._

-- 
John M. Chambers                  jmc@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
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._