[R-pkg-devel] Getting two independent packages with identical S3 generics to dispatch each other's methods

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Sat Jul 11 14:34:09 CEST 2020

On 11/07/2020 7:52 a.m., Pavel N. Krivitsky wrote:
> Dear Duncan et al.,
> Firstly, my apologies for the duplicated query. It seems that I had
> searched everywhere but the mailing list where I asked the question.
> Secondly, I was wondering if I could get some indication whether CRAN
> would accept a package with the following code and documentation (and
> only that):

I think it would depend on the documentation and the submission message. 
  You'll need to convince them not to reject your package under the "A 
package’s contribution has to be non-trivial" rule.  Explain why you 
can't put the generic in one of the existing packages and import it from 
there into the other one.  (I'd make ergm import lme4, since that only 
adds 5 packages that wouldn't otherwise be present:   "minqa" 
"nloptr"    "statmod"   "Rcpp"      "RcppEigen", and those are all 
reasonably popular packages.)

Duncan Murdoch

> 1) A number of exported generics of the form
> summary_formula(object, ..., lhs),
> simulate_formula(object, nsim=1, seed=NULL, ..., lhs),
> etc.,
> which expect a formula as their first argument, evaluate the LHS of the
> formula, and dispatch based on the class of the result, which can also
> be overridden by the lhs= argument.
> 2) Corresponding S3 methods summary.formula(), simulate.formula(), etc.
> methods, that call the corresponding *_formula() generic.
> I am familiar with the generics package, but I don't think it's a good
> place for this functionality, because this is not the typical
> dispatching behaviour, and because *.formula() exports are not
> technically generics but S3 methods. In particular, as far as I know,
> existing mechanisms make it easy to cherry-pick generics, but they
> don't make it easy to cherry-pick methods.
> 				Best Regards,
> 				Pavel
> On Sat, 2020-07-11 at 07:29 -0400, Duncan Murdoch wrote:
>> If the semantics of the two generics must remain identical in the
>> future, then there is an implicit dependency between the code in the
>> packages.  You should formalize this by using one of the dependency
>> mechanisms that the language provides, i.e. the clean solution.
>> Duncan Murdoch
>> On 10/07/2020 7:51 p.m., Pavel N. Krivitsky wrote:
>>> Dear All,
>>> I would like to have two packages that do not depend on each other
>>> that
>>> have an identical generic to be able to dispatch to each other's
>>> (non-
>>> conflicting) methods. If it is of interest, the background for why
>>> this
>>> is needed is given at the end of this e-mail.
>>> As it is, it looks like two packages that do not depend on each
>>> other
>>> both define a generic, they do not see each other's S3 methods.
>>> For example, in the two attached minimal packages, which define and
>>> export generic foo() (identical in both packages) and methods
>>> foo.character() and foo.numeric() that are exported via S3method(),
>>> we
>>> get,
>>>> library(test.character)
>>>> foo("a")
>>> foo.character() called.
>>>> library(test.numeric)
>>> Attaching package: ‘test.numeric’
>>> The following object is masked from ‘package:test.character’:
>>>       foo
>>>> foo(1)
>>> foo.numeric() called.
>>>> foo("a")
>>> Error in UseMethod("foo") :
>>>     no applicable method for 'foo' applied to an object of class
>>> "character"
>>> That is, test.numeric::foo() doesn't "see"
>>> test.character:::foo.character() and vice versa. Is there a way to
>>> make
>>> them see each other?
>>> This issue has arisen before, e.g. at
>>> https://stackoverflow.com/questions/25251136/how-to-conditionally-define-a-generic-function-in-r-namespace
>>> .
>>> The "clean" solution is, of course, to create a third package to
>>> define
>>> the generic that the two packages could import (and, if necessary,
>>> reexport). However, that involves creating an almost-empty package
>>> that
>>> then has to be submitted to CRAN, maintained, and add some amount
>>> of
>>> storage and computational overhead. Is there another way to do this
>>> that is transparent to the end user?
>>> # Background
>>> This arose as a result of two packages (lme4 and ergm) both wanting
>>> to
>>> implement a simulate.formula() method, causing conflicts when the
>>> user
>>> wanted to use both at the same time.
>>> ergm has a mechanism for dispatching based on the class of the LHS
>>> of
>>> the formula. It does so by defining a generic, simulate_formula()
>>> which
>>> evaluates the formula's LHS and dispatches a method (e.g.,
>>> simulate_formula.<CLASS>()) based on that.
>>> Since lme4 and ergm generally use different LHSs, we are thinking
>>> of
>>> resolving the conflict by copying the LHS dispatching mechanism
>>> from
>>> ergm to lme4, and then defining our own summary_formula methods as
>>> needed.
>>> 			Thank you in advance,
>>> 			Pavel
>>> ______________________________________________
>>> R-package-devel using r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-package-devel

More information about the R-package-devel mailing list