From jmc at research.bell-labs.com  Thu Jan  8 18:04:17 2004
From: jmc at research.bell-labs.com (John Chambers)
Date: Thu Jan  8 18:03:30 2004
Subject: [Rd] S3, S4, namespace
References: <8CBAA121CEB4D5118CB200508BB2BBEF05BF73F4@xmx8lonib.lonib.commerzbank.com>
Message-ID: <3FFD8D91.6CFFFE18@research.bell-labs.com>

You're caught in a subtle "gotcha" with the combination of things you're
doing.  We're trying to sort out some of the interactions among
namespace & methods at the moment, so there may be a nicer solution in
the future.  Meanwhile, I can tell you the problem and suggest various
work-arounds.

The basic problem is that by importing barpkg, rather than requiring it,
the generic version of "print" is not seen from the recursive call to
print inside the S4 method for class "bar".  (It's possible this is just
a simple bug, but the thread of environments is a bit tricky at this
point.)

Here's a dump (using options(error=recover)) of your example
(NameSpace4==wazpkg, NameSpace3==barpkg)

R> library(NameSpace4)
R> wazbar(99)
Error in .setMethodsForDispatch(f, fdef, resetMlist) : 
	Internal error: did not get a valid generic function object for
function "print"

Enter a frame number, or 0 to exit   
1:wazbar(99) 
2:barprint(new("bar", x)) 
3:barprint(new("bar", x)) 
4:print("barprint method for bar") 
5:MethodsListSelect("print", <environment>, structure(list(), methods =
structure( 
6:.setMethodsForDispatch(f, fdef, resetMlist) 
Selection: 5
Called from: eval(expr, envir, enclos)
Browse[1]> find("print")
[1] "package:base"

So only the S3 version of print on base is seen at this juncture. 
Hence, crash.

This leads to the first work-around: require(barpkg) (e.g., in a .onLoad
function for wazpkg)

R> require(NameSpace3)
Loading required package: NameSpace3 
[1] TRUE
R> wazbar(99)
[1] "barprint method for bar"
[1] 99

(because the S4 generic for print is now in the search path).

Other probable workarounds (haven't tried them out):

- force S4 generics for print, etc. in the wazbar package as well.

- don't make S3 generics on base into S4 generics.

John

"Heywood, Giles" wrote:
> 
> I have encountered an issue which I have been unable to resolve, involving
> an S3 generic (print) being declared S4 generic in a package, and the method
> being exported.  This all works fine - the problem occurs when I try to
> import the method to another package.
> 
> Here is the bit that works fine. -------------
> 
> #the .r file for package bar
> 
> setClass("bar",representation("numeric"))
> 
> if(!isGeneric("print")) {setGeneric("print",useAsDefault=print)}
> setMethod("print",signature(x="bar"),
>     print.bar <- function(x,...)
>         {
>         print("print method for bar")
>         print(x@.Data,...)
>         }
>     )
> 
> if(!isGeneric("barprint")) {setGeneric("barprint",useAsDefault=print)}
> setMethod("barprint",signature(x="bar"),
>     printBar <- function(x,...)
>         {
>         print("barprint method for bar")
>         print(x@.Data,...)
>         }
>     )
> 
> #the NAMESPACE file for package bar
> 
> import(methods)
> exportMethods(barprint,print)
> exportClasses("bar")
> 
> #then in R:
> 
> > require(barpkg)
> Loading required package: barpkg
> [1] TRUE
> > x <- new("bar",99)
> > print(x)
> [1] "print method for bar"
> [1] 99
> > barprint(x)
> [1] "barprint method for bar"
> [1] 99
> 
> Fine.
> 
> Here is the bit that I have not figured out. -------------
> 
> #the .r file for package waz
> 
> wazbar <- function(x)
>     {
>     barprint(new("bar",x))
>     }
> 
> #the NAMESPACE file for package waz
> 
> import(methods,barpkg)
> importMethodsFrom(barpkg)
> importClassesFrom(barpkg)
> export(wazbar)
> 
> #then in R
> 
> > require(wazpkg)
> Loading required package: wazpkg
> [1] TRUE
> > wazbar(99)
> Error in .setMethodsForDispatch(f, fdef, resetMlist) :
>         Internal error: did not get a valid generic function object for
> function "print"
> Error in print("barprint method for bar") :
>         S language method selection got an error when called from internal
> dispatch for function "print"
> 
> end of R bit ---------------------------
> 
> The problem goes away if I don't set print as an S4 generic in bar.
> 
> Can anyone help - maybe an error is obvious?
> 
> As a bit of background, I am package maintainer for its (Irregular
> Time-Series), and have been obliged to put it in a namespace or suffer a
> significant performance penalty (about 6x slower).  In the package I make S3
> generics (plot, print, summary etc) S4 generic in this package, and so far
> have not got into trouble for doing so.  However, I have now got stuck -
> possibly I have not seen the right documentation (I refer to the newsletter
> article, and John Chambers' correspondence on R-devel early September).
> 
> - Giles
> 
> platform i386-pc-mingw32
> arch     i386
> os       mingw32
> system   i386, mingw32
> status
> major    1
> minor    8.1
> year     2003
> month    11
> day      21
> language R
> 
> Rcmd install --doc="none"  barpkg
> 
> **********************************************************************
> This is a commercial communication from Commerzbank AG.\ \ T...{{dropped}}
> 
> ______________________________________________
> R-devel@stat.math.ethz.ch mailing list
> https://www.stat.math.ethz.ch/mailman/listinfo/r-devel

-- 
John M. Chambers                  jmc@bell-labs.com
Bell Labs, Lucent Technologies    office: (908)582-2681
700 Mountain Avenue, Room 2C-282  fax:    (908)582-3340
Murray Hill, NJ  07974            web: http://www.cs.bell-labs.com/~jmc


[Rd] S3, S4, namespace
John Chambers