[R-pkg-devel] Courtesy methods and explosive dependencies

Duncan Murdoch murdoch@dunc@n @ending from gm@il@com
Sat May 26 02:25:43 CEST 2018


On 25/05/2018 3:22 PM, Lenth, Russell V wrote:
>> There can't really be an "ImportGenerics", because S3 is so informal.  A generic function is a function that calls UseMethod, but it can do anything else as well.  So R would need some fancy code analysis to know whether it was safe to import the generic but not all the dependencies of that package, and that could change when the package holding the generic was updated.
>>
>> Examples of generics that do more than simply call UseMethod are rare, but they exist:  as.data.frame() and sort() are a couple.
>>
>> Duncan Murdoch
> 
> Right -- ImportGenerics was a dumb idea. However, Something like ImportNoDeps makes sense as an additional category in the DESCRIPTION file. In my example, if such existed, I could put in the DESCRIPTION file:
> 
>      ImportNoDeps: multcomp
> 
> This would signal that multcomp -- but not necessarily any of its dependencies -- is required to install emmeans.  And in the NAMESPACE file:
> 
>      importFrom(multcomp, cld)
>      S3method(cld, emmGrid)
> 
> ... would import the needed generic and register my new S3 method.
> 
> I think this kind of construct could significantly reduce dependencies for packages that extend other packages' methods.

But what happens if the multcomp maintainer modifies cld() next week 
(and makes no other change), so that it makes use of multcomp 
dependencies?  Your package would be claiming that it didn't need them, 
while multcomp would not have changed any of its declarations, just the 
code for that one function.  How would R know to generate an error in 
your package (because its claim about multcomp was now false)?  If it 
didn't, you'd end up in a situation where calls to cld() failed because 
the cld() generic no longer worked.

This is just too complicated.  If multcomp says that it needs 8 
packages, you shouldn't be able to install it without all of them.

On the other hand, I think you can do what you want as follows:

1.  Put multcomp into your Suggests list.  Users can choose to install 
it or not.

2.  Put a conditional define of the generic into one of your .R source 
files to define it for users who don't have multcomp:

if (!requireNamespace("multcomp"))
   cld <- function(object, ...) UseMethod("cld")

3.  In your NAMESPACE file, export cld, and conditionally import it for 
users who do have it:

export(cld)

if (requireNamespace("multcomp"))
   importFrom(multcomp, cld)


I haven't tested this much at all, but it appears to work on a very 
superficial test.

Duncan Murdoch



More information about the R-package-devel mailing list