From maechler at stat.math.ethz.ch  Fri Jul 15 19:19:43 2005
From: maechler at stat.math.ethz.ch (Martin Maechler)
Date: Fri, 15 Jul 2005 19:19:43 +0200
Subject: [Rd] S4 generics "missing"
In-Reply-To: <20050714232650.632EFA2CB@slim.kubism.ku.dk>
References: <20050714232650.632EFA2CB@slim.kubism.ku.dk>
Message-ID: <17111.61487.579787.821989@stat.math.ethz.ch>

Thank you, Lars, for persisting on this topic of
missing S4 generics!
[I'm diverting this away from the original bug report; 
 since this is really about future features rather than R bugs.]

Unfortunately it's not as easy as you might think. 
 
o  One reason is the fact that currently it is still necessary 
   for bootstrapping reasons that R "can run" with only the 'base'
   package loaded, i.e. "methods" not available.  This makes
   it sometimes hard to S4-ize base functions. 

o  Then there have been performance issues hindering the
   S4-ification of ``everything''.  
   Note that e.g. S4 classes , functions methods, etc are not really
   proper C-level SEXPs which would speed up (and lead to clean
   up) of the "methods" code base.

o  One other problem is with function like  cbind() which have
   a signature starting with '...' :  The need to be changed
   before you can define methods for them.
   
   We've recently started to discuss this issue within R core,
   with constructive proposals by John Chambers, and I have been
   strongly considering indeed to try the case of
   cbind() and rbind() in particular.

I also hope that some of these issues will be addressed during
this summer and will eventually lead to much improved S4
facilities in R.

Martin Maechler, ETH Zurich


>>>>> "lars" == lars  <lars at predict.com>
>>>>>     on Fri, 15 Jul 2005 01:26:50 +0200 (CEST) writes:

    lars> Hi,
    lars> I ran into another internal function that is missing S4 dispatch. It is 
    lars> the binary operator ":". Looking at the code, I see that it is actually 
    lars> a common problem. Other candidates are operators like "~", "&&", "||" 
    lars> and functions like: "length<-", "row", "col", "unlist", "cbind", etc. It 
    lars> would for instance be nice to be able to write a matrix class that has 
    lars> the same operators and functions as the built-in class. In general, I 
    lars> think that all the operators and functions associates with built-in 
    lars> types like vectors, lists, matrices and data frames should have S4 dispatch.

    lars> Thanks,
    lars> Lars


    lars> lars wrote:

    >> Hi,
    >> 
    >> OK, if you try to explicitly make them generic, you are told that they 
    >> are implicitly already generic:
    >> 
    >> > setGeneric("is.finite", function(from, ...) 
    >> standardGeneric("is.finite"))
    >> Error in setGeneric("is.finite", function(from, ...) 
    >> standardGeneric("is.finite")) :
    >> "is.finite" is a primitive function;  methods can be defined, but 
    >> the generic function is implicit, and can't be changed.
    >> 
    >> If you query about its genericness before you define you own generic, 
    >> you get:
    >> 
    >> > isGeneric("is.finite")
    >> [1] FALSE
    >> 
    >> But after you define you own generic, you get:
    >> 
    >> > setMethod("is.finite", signature(x="TS"),
    >> +           function(x) {
    >> +              Data(x) = callNextMethod()
    >> +              x
    >> +           })
    >> [1] "is.finite"
    >> 
    >> > isGeneric("is.finite")
    >> [1] TRUE
    >> 
    >> This all makes some sense, but I am not familiar enough with he 
    >> internals to explain exactly why it is done this way. I think you will 
    >> fine that 'is.nan' behave exactly the same way.
    >> 
    >> Thanks,
    >> Lars
    >> 
    >> 
    >> Prof Brian Ripley wrote:
    >> 
    >>> These functions are not generic according to the help page.
    >>> The same page says explicitly that is.nan is generic.
    >>> 
    >>> Where did you get the (false) idea that they were generic?
    >>> 
    >>> On Thu, 16 Jun 2005 lars at predict.com wrote:
    >>> 
    >>>> Full_Name: Lars Hansen
    >>>> Version: 2.1.0
    >>>> OS: SunOS 5.8
    >>>> Submission from: (NULL) (207.66.36.189)
    >>>> 
    >>>> 
    >>>> Hi,
    >>>> 
    >>>> S4 method displacth does not work for the two generic functions 
    >>>> 'is.finite' and 'is.infinite'. It turns out that the C functions 
    >>>> 'do_isfinite' and 'do_isinfinite' in src/main/coerce.c are missing a 
    >>>> call to 'DispatchOrEval' (see do_isnan). Added in the call fixed the 
    >>>> problem. My functions no look like this:
    >>>> 
    >>>> Form coerce.c:
    >>>> 
    >>>> SEXP do_isfinite(SEXP call, SEXP op, SEXP args, SEXP rho)
    >>>> {
    >>>> SEXP ans, x, names, dims;
    >>>> int i, n;
    >>>> 
    >>>> if (DispatchOrEval(call, op, "is.finite", args, rho, &ans, 1, 1))
    >>>> return(ans);
    >>>> 
    >>>> checkArity(op, args);
    >>>> ...
    >>>> 
    >>>> SEXP do_isinfinite(SEXP call, SEXP op, SEXP args, SEXP rho)
    >>>> {
    >>>> SEXP ans, x, names, dims;
    >>>> double xr, xi;
    >>>> int i, n;
    >>>> 
    >>>> if (DispatchOrEval(call, op, "is.infinite", args, rho, &ans, 1, 1))
    >>>> return(ans);
    >>>> 
    >>>> checkArity(op, args);
    >>>> ...



[Rd] S4 generics "missing"
Martin Maechler