If a package defined an S3 generic and an S4 generic for the same function (so as to add methods for S4 classes to the existing code), how do I set up the namespace to have them exported?
With
import(stats)
exportMethods(bigglm)
importClassesFrom(DBI)
useDynLib(biglm)
export(biglm)
export(bigglm)
in NAMESPACE, the S3 generic is not exported.
methods("bigglm")
[1] bigglm.RODBC* bigglm.data.frame* bigglm.function*
Non-visible functions are asterisked
Warning messages:
1: In findGeneric(generic.function, parent.frame()) :
'bigglm' is a formal generic function; S3 methods will not likely be found
2: In methods("bigglm") : function 'bigglm' appears not to be generic
[This is R 2.7.2, admittedly a little ancient]
-thomas
Thomas Lumley Assoc. Professor, Biostatistics
tlumley at u.washington.edu University of Washington, Seattle
You shouldn't have to export the S3 function: in the normal practice,
setGeneric("biglm") or just a setMethod("biglm", ....) will cause the S3
function (like any existing function) to become the default method for
the S4 generic. There is only one object called "biglm".
It's important though to use the default, one argument, call to
setGeneric(). Otherwise the two functions are not consistent and can't
exist in the same namespace. Also, the situation is different if the S3
function is in another package, as discussed in a previous thread here
recently.
The warning messages below, if they are still current, are misleading,
and usually outright wrong. The code should look at the default method
for the S4 generic.
John
PS: if this is the biglm() in the biglm package, the current CRAN
version is not a generic of any flavor. Presumably this is a new
version? Just curious, this has no effect on the above comments.
Thomas Lumley wrote:
If a package defined an S3 generic and an S4 generic for the same
function (so as to add methods for S4 classes to the existing code),
how do I set up the namespace to have them exported?
With import(stats)
exportMethods(bigglm)
importClassesFrom(DBI)
useDynLib(biglm)
export(biglm)
export(bigglm)
in NAMESPACE, the S3 generic is not exported.
methods("bigglm")
[1] bigglm.RODBC* bigglm.data.frame* bigglm.function*
Non-visible functions are asterisked
Warning messages:
1: In findGeneric(generic.function, parent.frame()) :
'bigglm' is a formal generic function; S3 methods will not likely be
found
2: In methods("bigglm") : function 'bigglm' appears not to be generic
[This is R 2.7.2, admittedly a little ancient]
-thomas
Thomas Lumley Assoc. Professor, Biostatistics
tlumley at u.washington.edu University of Washington, Seattle
It's important though to use the default, one argument, call to setGeneric().
Otherwise the two functions are not consistent and can't exist in the same
namespace.
Thanks. Does this include restricting which arguments are used for dispatch? I have
setGeneric("bigglm", signature=c("formula","data"))
to dispatch just on the first two arguments.
I will try to run everything on my desktop back in Seattle to see if there are still problems under r-devel -- my laptop is staying with its current version of R until my book goes to the publisher.
PS: if this is the biglm() in the biglm package, the current CRAN version is
not a generic of any flavor. Presumably this is a new version?
You're missing a 'g'. It's bigglm(), which is S3-generic already. The current version uses S3 inheritance on SQLiteConnection (which works, but doesn't extend to other DBIConnection objects, as you pointed out previously).
-thomas
Thomas Lumley Assoc. Professor, Biostatistics
tlumley at u.washington.edu University of Washington, Seattle
It's important though to use the default, one argument, call to
setGeneric(). Otherwise the two functions are not consistent and
can't exist in the same namespace.
Thanks. Does this include restricting which arguments are used for
dispatch? I have
setGeneric("bigglm", signature=c("formula","data"))
to dispatch just on the first two arguments.
That seems not to disturb anything. (It's really only the arguments
affecting the default that would break things directly. The other
non-defaults are a problem if multiple packages turn the same S3
function into a generic in inconsistent ways. But here you own both the
S3 and S4 versions.)
(R2.8.1)> foo <- function(x,y,z)UseMethod("foo")
(R2.8.1)> setGeneric("foo", signature = c("x", "y"))
[1] "foo"
(R2.8.1)> getMethod(foo) # the default
Method Definition (Class ?derivedDefaultMethod?):
function (x, y, z)
UseMethod("foo")
Signatures:
target
defined
(R2.8.1)> foo at signature
[1] "x" "y"
I'm still having problems getting a package to define both S3 and S4 methods for the same new generic, on a current r-devel (version 48144).
Symptoms
example(bigglm)
bigglm> data(trees)
bigglm> ff<-log(Volume)~log(Girth)+log(Height)
bigglm> a <- bigglm(ff,data=trees, chunksize=10, sandwich=TRUE)
Error in UseMethod("bigglm", data) : no applicable method for "bigglm"
standardGeneric for "bigglm" defined from package "biglm"
function (formula, data, family = gaussian(), ...)
standardGeneric("bigglm")
<environment: 0x8554240>
Methods may be defined for arguments: formula, data
Use showMethods("bigglm") for currently available ones.
getMethod("bigglm",c("ANY","ANY"))
Method Definition (Class "derivedDefaultMethod"):
function (formula, data, family = gaussian(), ...)
UseMethod("bigglm", data)
<environment: namespace:biglm>
Signatures:
formula data
target "ANY" "ANY"
defined "ANY" "ANY"
methods("bigglm")
[1] bigglm.data.frame* bigglm.function* bigglm.RODBC*
Non-visible functions are asterisked
Warning messages:
1: In findGeneric(generic.function, parent.frame()) :
'bigglm' is a formal generic function; S3 methods will not likely be found
2: In methods("bigglm") : function 'bigglm' appears not to be generic
In the NAMESPACE file I have
import(stats)
useDynLib(biglm)
importClassesFrom(DBI)
exportMethods(bigglm)
export(biglm)
export(bigglm)
S3method(bigglm,data.frame)
S3method(bigglm,"function")
S3method(bigglm, RODBC)
and in the code
bigglm<-function(formula, data, family=gaussian(),...)
UseMethod("bigglm", data)
setGeneric("bigglm", signature=c("formula","data"))
bigglm.data.frame<-function(formula, data, ..., chunksize=5000){ <snip>
setMethod("bigglm",
c("ANY","DBIConnection"),
function(formula, data, family = gaussian(),
tablename, ..., chunksize=5000){
terms<-terms(formula)
modelvars<-all.vars(formula)
<snip>
Any suggestions?
-thomas
Thomas Lumley Assoc. Professor, Biostatistics
tlumley at u.washington.edu University of Washington, Seattle
Could you send me your package code, off-list. I think the problem may
be related to non-exported S3 method objects.
John
Thomas Lumley wrote:
I'm still having problems getting a package to define both S3 and S4
methods for the same new generic, on a current r-devel (version 48144).
Symptoms
example(bigglm)
bigglm> data(trees)
bigglm> ff<-log(Volume)~log(Girth)+log(Height)
bigglm> a <- bigglm(ff,data=trees, chunksize=10, sandwich=TRUE)
Error in UseMethod("bigglm", data) : no applicable method for "bigglm"
standardGeneric for "bigglm" defined from package "biglm"
function (formula, data, family = gaussian(), ...)
standardGeneric("bigglm")
<environment: 0x8554240>
Methods may be defined for arguments: formula, data
Use showMethods("bigglm") for currently available ones.
getMethod("bigglm",c("ANY","ANY"))
Method Definition (Class "derivedDefaultMethod"):
function (formula, data, family = gaussian(), ...) UseMethod("bigglm",
data)
<environment: namespace:biglm>
Signatures:
formula data target "ANY" "ANY"
defined "ANY" "ANY"
methods("bigglm")
[1] bigglm.data.frame* bigglm.function* bigglm.RODBC*
Non-visible functions are asterisked
Warning messages:
1: In findGeneric(generic.function, parent.frame()) :
'bigglm' is a formal generic function; S3 methods will not likely be
found
2: In methods("bigglm") : function 'bigglm' appears not to be generic
In the NAMESPACE file I have
import(stats)
useDynLib(biglm)
importClassesFrom(DBI)
exportMethods(bigglm)
export(biglm)
export(bigglm)
S3method(bigglm,data.frame)
S3method(bigglm,"function")
S3method(bigglm, RODBC)
and in the code
bigglm<-function(formula, data, family=gaussian(),...)
UseMethod("bigglm", data)
setGeneric("bigglm", signature=c("formula","data"))
bigglm.data.frame<-function(formula, data, ..., chunksize=5000){ <snip>
setMethod("bigglm",
c("ANY","DBIConnection"),
function(formula, data, family = gaussian(),
tablename, ..., chunksize=5000){
terms<-terms(formula)
modelvars<-all.vars(formula)
<snip>
Any suggestions?
-thomas
Thomas Lumley Assoc. Professor, Biostatistics
tlumley at u.washington.edu University of Washington, Seattle