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

Robert Gentleman rgentlem@hsph.harvard.edu
Thu, 15 Apr 1999 12:38:27 -0400 (EDT)



On Fri, 16 Apr 1999, Bill Venables wrote:

> Blundering late into this discussion I'm going to take a chance
> here and venture an opinion on what does happen in S3 UseMethod,
> regardless of what interpretations are made of A.6 in the white
> book.  This is by the "suck it and see" method, the only one I
> trust.  (The chance I take is in supposing this to be useful...)
> 
> 1. At the time of the UseMethod call the principal argument is
>    examined, and evaluated if necessary, and the class it has at
>    that stage is the one used for method dispatch.
> 
> 2. All non-missing arguments are passed on to the method with the
>    values they were supplied with at the time of the original
>    call, not the changed values they may have at the time of
>    dispatch, (including the principal argument).
> 
> 3. Missing arguments that have been given values at the time of
>    method dispatch, as well as local variables, retain their
>    current values when control passes to the method.
> 
> 4. Supplying a second argument to UseMethod() allows some other
>    argument than the first to act as the principal argument.
> 
> 5. Default values for arguments in the method supercede defaults
>    supplied in the generic.
> 
> The method directly occupies the frame of the generic, but
> arguments actually supplied to the generic re-assume their
> original supplied values (even though changes to the principal
> argument prior to method dispatch may determine mathod dispatch.)

  I don't think that's what S does. My experiments suggest that S
takes the current value of the principal argument regardless of
what was passed in. I asked JMC and if I understood him then that's
what is being done.
  As for other arguments, well it seems to pick things up at the point
that UseMethod is called from.
  For example,
  bar<-function(w, y, ...)
{
        y <- 12
        w <- 3
        UseMethod("bar")
}
  bar.default<-function(y, w) {
     print(w)
     print(y)
  }

  x<-30
  bar(x)

  yields:
[1] 3
[1] 12
[1] 12

  So, x was changed, y (even though missing from the original call
 now exists) and the names given to the arguments in the call to
 the generic have been used to match in the call to the method.

 In R, (0.65)
 I get 
  > Error: Argument "w" is missing, with no default.


 One small change (and back to S) 
  bar<- function(w, v, ...)
{
        y <- 12
        w <- 3
        UseMethod("bar")
}

  Now, for bar(x,20) I still get,
[1] 3
[1] 12
[1] 12
 
  I don't think that's what you want. But my guess as to the semantics
is the following.
  When UseMethod is called the generic is determined by the class
of the principal argument at that point. That method is grabbed
and it's arguments are matched using the frame of the currently
executing method (not the arguments in the call to the currently 
active method). Then that method is evaluated using a new frame,
but the bindings achieved from the match. 

We can do this; but do we want to? There is something particularly
unsettling about the method matching args from the currently active frame
rather than from the call to the generic.

  I'm working with:
S-PLUS : Copyright (c) 1988, 1996 MathSoft, Inc.
S : Copyright AT&T.
Version 3.4 Release 1 for Sun SPARC, SunOS 5.3 : 1996 

> 
> So, for example, if the principal argument is not missing, has no
> class at the call and is given class "xyz" by the generic, the
> "xyz" method is dispatched, but the object corresponding to the
> principal argument inside the method is the original classless
> object.  (I would have thought that this was the major reason to
> have a function like data.class in the first place.  What other
> serious use does it have?)  To verify *from within the method*
> that the principal argument had the class implied by the method,
> you have to inspect the .Class guaranteed variable, not the
> current class of the principal argument itself, which may be
> wildly at variance.
> 
> "Missing" arguments on the original call remain missing unless
> the generic has given them values prior to method dispatch, in
> which case they behave like local variables and retain their
> local supplied values.  If defaults are needed, the most recent
> one is used.
> 
> Now, how does R differ?
> 
> Bill Venables.
> -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
> 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
> _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
> 

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