R's UseMethod() does not dispatch on changed class() (PR#167)

ripley@stats.ox.ac.uk ripley@stats.ox.ac.uk
Thu, 15 Apr 1999 08:39:49 +0200


On Wed, 14 Apr 1999, Robert Gentleman wrote:

> On Wed, 14 Apr 1999, Prof Brian D Ripley wrote:
> 
> > On 15 Apr 1999, Peter Dalgaard BSA wrote:
> > 
> > > Robert Gentleman <rgentlem@hsph.harvard.edu> writes:
> > > 
> > > > Do you really want to have a language that accepts any change in x?
> > > > It is rather hard to see how it's object oriented then!
> > > > Or, alternatively do you really want to see if the only thing that
> > > > has changed about x is its class and that will be ok?
> > > > What about the other arguments?
> > > > The whole point of UseMethod is that we got an object x, with a
> > > > particular class and now we're going to do the right thing.
> > > > If you wanted to do the right thing with an object of a different
> > > > class then you need to do that before you call UseMethod.
> > > 
> > > I'm inclined to agree here. On the other hand, what might be the case
> > > is that you could make class<- be a little more careful with its
> > > argument so that UseMethod would see the modified x. Sneaky, but
> > > compatible, and *perhaps* not very hard to do. How often is this kind
> > > of construct (class(x)<-foo;UseMethod()) used in actual S code?
> > 
> > Often by certain people with a massive presence!
> > 
> > We have indeed been here before.  In our lda function we do
> > 
> > class(x) <- data.class(x)
> > UseMethod("lda")
> > 
> > That fails to use the new class in R, and according to `your' reading of
> > the White book (but not mine nor apparently the author of S's) should do
> > so. `You' suggested
> 
>  If you could point out the error of my ways I would appreciate it.

I did not mean to imply that you were wrong, rather that the White Book
can be read both ways (and it seems has been).

> But, it as I understand it, UseMethod is supposed to call the method
> with the arguments the same as those that called the generic. You
> must evaluate x to figure out what method to call, but I don't see
> how you can change x (adding classes is changing it).

Then why are

UseMethod("foo")
UseMethod("foo", x)

different in R? (They are: lda works.) The actual definition of UseMethod
in S is

       UseMethod(generic, object, ...)

and by the standard evaluation model, `object' is subject to lazy
evaluation. Nothing I can see in the White Book says otherwise. Indeed,
page 467 says the arguments are `re-matched by the standard rules'. It then
says `The method will see argument matches as it would if the user's call
had been directly to the method'.  I think those claims are contradictory,
and in particular whichever way they are read suggest my pair of calls
should be the same.

[In S UseMethod("foo") is semantic shorthand for UseMethod("foo", <name of
first argument of caller>), according to the help page.]

To make matters worse, in S it is a common mistake to have

foo <- function(x, ...) UseMethod("foo")
foo.lm <- function(y, ...) { .... }

and that change of name of argument causes re-evaluation.  What happens in
R?  This makes an apparently small point, that generics should have the
same argument name as S, potentially rather important. I know of four
outstanding discrepancies:

R: deviance <- function (x, ...) UseMethod("deviance")
S: deviance <- function (x, ...) UseMethod("deviance")

and ditto for coef, fitted, residuals (which I had not realized, in part
because some of these only recently acquited defaults).

There are inconsistencies in the current R code: any objections if
I change these to uniformly follow S and use `object'?


The other common one is `print'. As in

> print
function (x, ...) 
UseMethod("print")
> print.socket
function (socket) 
{
    cat("Socket connection #", socket$socket, "to", socket$host, 
        "on port", socket$port, "\n")
}

print methods should have first argument x, a ... argument _and_ return
invisible(x) for an unchanged x (in S, at least).  print.plot
does not even have an argument, so how does that ever work?

>   I realize it is frustrating and if you think it's important
> you should change it. But, by doing that you move the language
> further away from being object oriented. 

What we do need is to get this documented!  In particular, in R

> ?UseMethod

Class Methods

     UseMethod(name)

is incomplete, and I only know about UseMethod("foo", x, ...) because
`you' (Kurt?) suggested I use it. 

BTW, I have never believed S3's claim to be `object-oriented': it has a
class-based dispatcher. S has changed (although it remains to be seen if
users will follow) and I would be happy for R to be different from both.
However, as Bill and I are currently trying to write about this for V&R3v2,
I would not like R to change dramatically after the next few months!


Brian

-- 
Brian D. Ripley,                  ripley@stats.ox.ac.uk
Professor of Applied Statistics,  http://www.stats.ox.ac.uk/~ripley/
University of Oxford,             Tel:  +44 1865 272861 (self)
1 South Parks Road,                     +44 1865 272860 (secr)
Oxford OX1 3TG, UK                Fax:  +44 1865 272595


-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
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
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._