[R] S4 method dispatch matrixOrArray

Martin Maechler maechler at stat.math.ethz.ch
Thu Apr 13 09:23:29 CEST 2006


>>>>> "Gabor" == Gabor Grothendieck <ggrothendieck at gmail.com>
>>>>>     on Wed, 12 Apr 2006 18:24:46 -0400 writes:

    Gabor> This is surprising.  I would have thought that the
    Gabor> parent/child relationships determine the order that
    Gabor> dispatched methods are invoked, not the order that
    Gabor> the setMethod commands are issued in.

My expectations here agree with Gabor's.
Paul, can you demonstrate your claim,
namely that the  *order* of the setMethod(.) statements determines
dispatch behavior ?  I believe that would be faulty.

IIRC, a more "interesting" case of dispatch behavior is the
one where you have multiple *inheritance*, i.e., have a class
with more than one superclass ("parent").  If methods for two
superclasses are defined, some dispatch order has to be
established, and IIRC some of us have agreed that dispatch order
for methods should follow "contains order" of the superclasses
(in the class at hand) -- and I think that's even the case now.

Martin

    Gabor> On 4/12/06, Paul Roebuck <roebuck at mdanderson.org>
    Gabor> wrote:
    >> On Wed, 12 Apr 2006, Gabor Grothendieck wrote:
    >> 
    >> > On 4/12/06, Paul Roebuck <roebuck at mdanderson.org>
    >> wrote:
    >> >
    >> > > I have some code where the primary dispatching is on
    >> > > other parameters so I'd like not to have to create a
    >> > > set of functions for "matrix" and another duplicate >
    >> > set for "array". But the class union technique isn't >
    >> > working as implemented below and I don't have my Green
    >> > > book with me. How do I fix my infinite recursion
    >> problem?
    >> > >
    >> > >
    >> > > ##--------------------------------------------------------
    >> > > library(methods)
    >> > >
    >> > > setGeneric("foo", > > function(A, ...) { > >
    >> cat("generic", match.call()[[1]], "\n") > >
    >> standardGeneric("foo") > > })
    >> > >
    >> > > setMethod("foo", > > signature(A = "vector"), > >
    >> function(A, ...) { > > callGeneric(matrix(A, nrow = 1),
    >> ...)  > > })
    >> > >
    >> > > setClassUnion("matrixOrArray", c("matrix", "array"))
    >> > >
    >> > > setMethod("foo", > > signature(A = "matrixOrArray"),
    >> > > function(A, ...) { > > cat("A =", A, "\n") > > })
    >> > >
    >> > > ## Test > > foo(1:4) > > foo(matrix(1:4, 1, 4)) > >
    >> foo(array(1:4, c(1, 4, 1)))
    >> >
    >> > I think its good enough to just define an array method,
    >> i.e. you > don't need the matrix method or the
    >> matrixOrArray class, and the > vector method can call
    >> foo(matrix(A,1), ...) so:
    >> >
    >> > setGeneric("foo", > function(A, ...) { > cat("generic",
    >> match.call()[[1]], "\n") > standardGeneric("foo") > })
    >> >
    >> > setMethod("foo", > signature(A = "array"), >
    >> function(A, ...) { > cat("A =", A, "\n") > })
    >> >
    >> > setMethod("foo", > signature(A = "vector"), >
    >> function(A, ...) { > foo(matrix(A, nrow = 1), ...)  > })
    >> 
    >> Something didn't seem right here. That was pretty close
    >> to what I had started with, before trying to go the
    >> classUnion route. Matter of fact, the vector method can
    >> retain use of callGeneric.
    >> 
    >> The solution has to do with the order in which calls to
    >> setMethod are made. Adding foo-vector after foo-array
    >> works fine; the other way around causes infinite
    >> recursion.
    >> 
    >> ----------------------------------------------------------
    >> SIGSIG -- signature too long (core dumped)
    >>




More information about the R-help mailing list