From ross at biostat.ucsf.edu  Sat Dec  2 18:05:33 2006
From: ross at biostat.ucsf.edu (Ross Boylan)
Date: Sat, 2 Dec 2006 09:05:33 -0800
Subject: [Rd] promptClass misses methods
In-Reply-To: <17777.42410.517603.635881@stat.math.ethz.ch>
References: <20061201062906.GB8201@wheat.betterworld.us>
	<17776.1530.328130.767021@stat.math.ethz.ch>
	<20061201193320.GY4431@wheat.betterworld.us>
	<17777.42410.517603.635881@stat.math.ethz.ch>
Message-ID: <20061202170533.GA4431@wheat.betterworld.us>

On Sat, Dec 02, 2006 at 05:11:22PM +0100, Martin Maechler wrote:
> >>>>> "RossB" == Ross Boylan <ross at biostat.ucsf.edu>
> >>>>>     on Fri, 1 Dec 2006 11:33:21 -0800 writes:
> 
>     RossB> On Fri, Dec 01, 2006 at 11:37:46AM +0100, Martin
>     RossB> Maechler wrote:
>     >> >>>>> "RossB" == Ross Boylan <ross at biostat.ucsf.edu>
>     >> >>>>> on Thu, 30 Nov 2006 22:29:06 -0800 writes:
>     >> 
>     RossB> I've had repeated problems with promptClass missing
>     RossB> methods, usually telling me a class has no methods
>     RossB> when it does.
>     >>
>     RossB> In my current case, I've defined an S4 class
>     RossB> "mspathCoefficients" with a print method
>     RossB> setMethod("print", signature(x="mspathCoefficients"),
>     RossB> function(x, ...)  { # etc
>     >>  You should *not* define "print" methods for S4 classes;
>     >> rather you should define "show" methods.
> 
>     RossB> Is that because print is used by the S3 system?  
> 
> no, not really.
>     RossB> And is the general rule to avoid using S3 methods for S4
>     RossB> classes?
> 
> Well your wording is murky, but no, you *should* define (S4) methods 
> for S3 generics very well.  The S3 generics are automagically
> promoted to S4 generics as soon as you define an S4 method for it.

That answers my question.  The meaning was if "foo" is an S3 method,
should one avoid defining "foo" as an S4 method.  And the answer is
no, it's OK.  I assume one should strive to use the same argument
names, although since S3 methods don't need to use the same argument
names I'm not sure how that works (e.g. for S3
  foo.class1 <- function(x, a, b) but
  foo.class2 <- function(x, c)
). 

> 
> print() is just a big exception.
> 

How come?  

Is it an exception in the sense that it is not automatically used to
display the object, or in the sense that one should never define S4
print methods at all?  (Looks like the first alternative based on the
example later.)  The print methods I have seem to work OK, provided I
don't expect them to be called automatically and provided I don't
expect promptClass to pick them up.


>     RossB>   For example, http://www.omegahat.org/RSMethods/Intro.pdf, which is
>     RossB> referenced in the package help for methods, discusses
>     RossB> show, print and plot as 3 alternatives in S4 (p. 9,
>     RossB> though a footnote says that at that time--2001--R
>     RossB> didn't recognize formal methods for printing
>     RossB> objects.)
> 
> 2001 is way in the past concerning S4 implementation in R.

Perhaps the reference should be removed then.  Maybe the newer
http://developer.r-project.org/howMethodsWork.pdf would be better?
However, that is pitched more toward the internals, and is already
referenced in ?Methods.

> Specifically, using S4 in R; we'd   **very strongly** recommend
> R 2.4.0 (and ideally even R-patched) because of several recent
> good developments.

Fortunately that's what I'm using.  I wonder if this is so important I
should require R >= 2.4 for my package.  It was working fine in
earlier versions.  The main user visible changes I'm aware of are
those in the object forms (i.e., binary incompatibility) and some
improvements in the algorithm for choosing which method to dispatch to
(semantically, sometimes a different method gets called; it sounds
faster too).  I'm not distributing any data files with S4 class
objects, and don't have any corner cases on method dispatch.

> 
>     RossB> I've been unable to locate much information about
>     RossB> combining S3 and S4 methods, though I recall seeing a
>     RossB> note saying this issue was still to be addressed in
>     RossB> R.  Perhaps it has been now, with setOldClass?  At
>     RossB> any rate, the help for that method addresses classes
>     RossB> rather than methods, and I didn't see anything in
>     RossB> ?Methods, ?setMethod, or ?setGeneric.
> 
>     RossB> show() raises two additional issues for me.  First,
>     RossB> it takes a single argument, and I want to be able to
>     RossB> pass in additional arguments via ... .  
> 
> That's not possible currently.

In the expected use of show(), namely automatically showing an object,
additional arguments don't make sense (since there's no chance to
provide them).

If the only problem in my use of print is that it's not called
automatically, then perhaps I should leave it as is and define a show
method that invokes print().  That seems to be the pattern in the
example you provided below.

> 
> And I agree that in certain cases, I would want to have the
> flexibility of print(..) there;
> One case is for printing/showing fitted LMER objects; the
> following code is used :
> 
>   ## This is modeled a bit after  print.summary.lm :
>   printMer <- function(x, digits = max(3, getOption("digits") - 3),
> 		       correlation = TRUE, symbolic.cor = x$symbolic.cor,
> 		       signif.stars = getOption("show.signif.stars"), ...)
>   {
> 	  ...............
> 	  ...............
>       invisible(x)
>   }
> 
>   setMethod("print", "mer", printMer)
>   setMethod("show", "mer", function(object) printMer(object))
> 
> 
>     RossB> Second, I read some advice somewhere, that I no
>     RossB> longer can find, that show methods should return an
>     RossB> object and that object in turn should be the thing
>     RossB> that is printed.  I don't understand the motivation
>     RossB> for that rule, at least in this case, because my
>     RossB> object is already a results object.
> 
> I  think you're confusing show() with summary(): The latter is
> should typically compute an object which then has a print/show
> method.
Yes, that's it.  And that all makes sense.
> 
> 
>     RossB> The file promptClass creates has no methods in it.
>     >> >> showMethods(classes="mspathCoefficients")
>     RossB> Function: initialize (package methods)
>     RossB> .Object="mspathCoefficients" (inherited from:
>     RossB> .Object="ANY")
>     >>  so it's just inherited from "ANY"
>     >> 
>     RossB> Function: print (package base) x="mspathCoefficients"
>     >>  that's the one
> 
>     RossB> So why isn't promptClass picking it up?
> 
>     >>
>     RossB> Function: show (package methods)
>     RossB> object="mspathCoefficients" (inherited from:
>     RossB> object="ANY")
>     >> so it's just inherited from "ANY"
>     >> 
>     >> Ross, it would really be more polite to your readers if
>     >> you followed the posting guide and posted complete
>     >> fully-reproducible code...
> 
>     RossB> I thought it might be overkill in this case.  
> 
> It never is. We do want self-contained executable code..
> In your case, I assumed it might have been things in a namespace
> in a package, ...
> 
>     RossB> At any rate, it sounds as if I may be trying to do the wrong
>     RossB> thing, so I'd appreciate guidance on what the right
>     RossB> thing to do is.
> 
>     RossB> Here's a toy example:
> 
>     RossB> setClass("A", representation(x="numeric"))
>     RossB> setMethod("print", signature(x="A"), function(x, ...) print(x at x, ...) )
>     RossB> promptClass("A")
> 
>     RossB> The generated file has no print method.
>  
> Indeed, I can confirm that.
> 
>     >> >> getGeneric("print")
>     RossB> standardGeneric for "print" defined from package
>     RossB> "base"
>     >> 
>     RossB> function (x, ...)  standardGeneric("print")
>     RossB> <environment: 0x84f2d88> Methods may be defined for
>     RossB> arguments: x
>     >> 
>     >> 
>     RossB> I've looked through the code for promptClass, but
>     RossB> nothing popped out at me.
>     >> 
>     RossB> It may be relevant that I'm running under ESS in
>     RossB> emacs.  However, I get the same results running R
>     RossB> from the command line.
>     >> 
>     RossB> Can anyone tell me what's going on here?  This is
>     RossB> with R 2.4, and I'm not currently using any namespace
>     RossB> for my definitions.
> 
>     >> [and not a package either?]
>     RossB> The code is part of  a package, but I'm developing code snippets in
>     RossB> ESS without loading the whole package.
>     >> 
>     >> I'm very willing to look at this, once
>     >> you've provided what the posting guide asks for, see above.
> 
> so now that I've promissed it; I'll have to look at it ;-)
> Probably too late to get a fix into R 2.4.1 though.

Ah, so the lack of a print method in the promptClass output is a bug?

Ross



[Rd] promptClass misses methods
Ross Boylan