[Rd] S4 NAMESPACE method imports and exports do not include (promoted?) generics

John Chambers jmc at r-project.org
Fri Dec 16 21:19:48 CET 2011

The subject heading is correct if referring to  exportMethods() and 
importMethodsFrom().  They refer to the methods tables, not the generic 
functions, whatever the extensions manual says.

Looking into the code of namespaceImportMethods() will illustrate this. 
  It just deals with lists of method tables obtained from .getGenerics() 
which in spite of its name also only looks for the method table metadata 

As I vaguely recall, there was some concern at one time about having 
extra copies of the generic version of the function.

The fundamental problem is that creating methods for unique(), say, does 
not change the way calls to base::unique() work.  Therefore, all 
packages that want to use methods have to ensure that a generic version 
of unique gets in between.   Primitive functions are an exception 
because the method dispatch is in the C code and has a rule for checking 
when given an S4 object.  There is no corresponding provision for 
evaluating a call to a regular function.

If the importing package has a setGeneric() for the relevant function 
then its own namespace has the generic version of the function.  (That 
is a workaround, but I inferred that was what you were trying to avoid.)

Fixes seem possible, but some care is needed.  If exportMethods 
automatically exported the generic function, it really is no different 
from export() for that function.

namespaceImportMethods() could try to supply the generic function if it 
is not already present.  If it does not find the generic in the 
namespace being imported, it would essentially have to call 
setGeneric(), assuming the non-generic function exists in the specified 
package (e.g., in base for unique()).


On 12/16/11 6:16 AM, Martin Morgan wrote:
> tar of Pkgs A, B, C attached. Martin
> On 12/15/2011 03:34 PM, Martin Morgan wrote:
>> In
>> > R.version.string
>> [1] "R Under development (unstable) (2011-12-15 r57901)"
>> section 1.6.6 of 'Writing R Extensions' says
>> Note that exporting methods on a generic in the namespace will
>> also export the generic, and exporting a generic in the
>> namespace will also export its methods.
>> and
>> Note that importMethodsFrom will also import any generics defined in
>> the namespace on those methods
>> However, if PkgA promotes 'unique' to a generic and exports that
>> Imports: methods
>> R/f.R:
>> setGeneric("unique")
>> export(unique)
>> and PkgB creates and exports a method on unique
>> Imports: methods, PkgA
>> R/f.R:
>> setClass("B", representation(b="numeric"))
>> setMethod(unique, "B",
>> function(x, incomparables=FALSE, ...) unique(x at b))
>> importFrom(PkgA, unique)
>> exportClasses(B)
>> exportMethods(unique)
>> and PkgC wants to import PkgB's classes and methods
>> Imports: methods, PkgB
>> R/f.R
>> cunique <- function(x) unique(x)
>> importMethodsFrom(PkgB, unique)
>> export(cunique)
>> then
>> (a) the 'unique' generic is not available to the user of PkgB
>> > library(PkgB)
>> > unique(new("B", b=1:5))
>> Error in unique.default(new("B", b = 1:5)) :
>> unique() applies only to vectors
>> and (b) the generic has not been imported to PkgC's namespace
>> > cunique(new("B", b=1:5))
>> Error in unique.default(b) : unique() applies only to vectors
>> A workaround is for PkgB to also export(unique), and for PkgC to also
>> importFrom(PkgA, unique), but is this the intention?
>> This is arising from Bioconductor efforts to place commonly promoted
>> functions and S3 classes into a single package, to avoid conflicts when
>> the same function is promoted independently by several packages.
>> Martin

More information about the R-devel mailing list