Skip to content

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

1 message · Brian Ripley

#
On Wed, 14 Apr 1999, Robert Gentleman wrote:

            
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).
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
function (x, ...) 
UseMethod("print")
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?
What we do need is to get this documented!  In particular, in R
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