[R-pkg-devel] Two packages with the same generic function

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Tue Jun 23 12:10:38 CEST 2020


On 22/06/2020 10:17 p.m., Bert Gunter wrote:
> "Users don't get warned about overriding names in packages they've
> loaded, because that would just be irritating."
> 
> Is that also true if the package or generic is imported by another that 
> they load; or is a dependency of a package they load? If so, I would not 
> call it "just irritating" because if silent, how would they know?

I can't think of an example where this would be a problem.  If a package 
imports objects from another package, it doesn't affect the user's 
search list.  Maybe it affects what methods are available, but I can't 
see how it would change what generics are available.

Can you give an example of what you're worried about?

Duncan Murdoch

> 
> 
> Bert Gunter
> 
> "The trouble with having an open mind is that people keep coming along 
> and sticking things into it."
> -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip )
> 
> 
> On Mon, Jun 22, 2020 at 5:58 PM Mark Leeds <markleeds2 using gmail.com 
> <mailto:markleeds2 using gmail.com>> wrote:
> 
>     Hi Duncan: I maintain dynlm and your example is the exact reason
>     I've been
>     getting emails from people regarding
>     it not working correctly. I've been telling them to load dplyr by using
> 
>     library(dplyr, exclude = c("filter", "lag"))
> 
> 
> 
> 
> 
>     On Mon, Jun 22, 2020 at 7:57 PM Duncan Murdoch
>     <murdoch.duncan using gmail.com <mailto:murdoch.duncan using gmail.com>>
>     wrote:
> 
>      > On 22/06/2020 3:48 p.m., Tom Wainwright wrote:
>      > > Yet another alternative is simply to prevent your second
>     package from
>      > > overriding the previously defined generic. The basic problem is
>     the ease
>      > > with which R allows overriding prior generic definitions (one
>     of those
>      > bits
>      > > of bad behavior we in the USA used to call "a Bozo No-No"),
>     which hides
>      > all
>      > > the previous methods, as demonstrated by the following code:
>      > >
>      > >> plot(1:3)
>      > >>> plot <- function(x, ...) UseMethod("plot")
>      > >>> plot(1:3)
>      > >> Error in UseMethod("plot") :
>      > >>    no applicable method for 'plot' applied to an object of class
>      > >> "c('integer', 'numeric')"
>      > >>> rm(plot)
>      > >>> plot(1:3)
>      > >
>      > >
>      > > (Despite Murdoch's suggestion that overriding the generic
>     SHOULD issue a
>      > > warning, it doesn't seem to in R 4.0.1.)
>      >
>      > Sure it does, if pkgA and pkgB both export the same name, then
>     you get a
>      > warning when you attach the second one.  For example,
>      >
>      >  > library(MASS)
>      >  > library(dplyr)
>      >
>      > Attaching package: ‘dplyr’
>      >
>      > The following object is masked from ‘package:MASS’:
>      >
>      >      select
>      >
>      > The following objects are masked from ‘package:stats’:
>      >
>      >      filter, lag
>      >
>      > The following objects are masked from ‘package:base’:
>      >
>      >      intersect, setdiff, setequal, union
>      >
>      > Users don't get warned about overriding names in packages they've
>      > loaded, because that would just be irritating.
>      >
>      > Duncan Murdoch
>      >
>      > >
>      > > So, we might try protecting the generic definitions of "foo" in
>     both
>      > > packages by enclosing them in something like:
>      > >
>      > > tryCatch(invisible(methods("foo")), error = {foo <- function(x,...)
>      > >> UseMethod("foo")}, finally=NULL)
>      > >
>      > >
>      > > There's probably a more elegant way to accomplish this. This
>     relies on
>      > > "methods" returning an error if "foo" has no defined methods,
>     so it is
>      > not
>      > > redefined if their are previous methods. I haven't had time to
>     try this
>      > in
>      > > the two-package example, but it might work, although I'm not
>     sure how to
>      > > handle the Namespace declarations.
>      > >
>      > >    Tom Wainwright
>      > >
>      > > On Mon, Jun 22, 2020 at 10:41 AM Bert Gunter
>     <bgunter.4567 using gmail.com <mailto:bgunter.4567 using gmail.com>>
>      > wrote:
>      > >
>      > >> ...
>      > >> and just to add to the query, assume the author of pkg B did
>     (does) not
>      > >> know of pkg A and so, for example, could (did) not import any
>     of pkg A's
>      > >> content into B. Given that there are at the moment ~20,000
>     packages out
>      > >> there, this does not seem to be an unreasonable assumption.
>     One may even
>      > >> further assume that the user may not know that (s)he has package B
>      > loaded,
>      > >> as it may be a dependency of another package that (s)he uses. I
>      > certainly
>      > >> don't keep track of all the dependencies of packages I use.
>      > >>
>      > >> Under these assumptions, is there any more convenient
>     alternative to
>      > >> Wolfgang's pkgA:foo(x) explicit call under such assumptions?
>     If pkgA
>      > has a
>      > >> long name, what might one do?
>      > >>
>      > >> Bert Gunter
>      > >>
>      > >> "The trouble with having an open mind is that people keep
>     coming along
>      > and
>      > >> sticking things into it."
>      > >> -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip )
>      > >>
>      > >>
>      > >> On Mon, Jun 22, 2020 at 10:00 AM Viechtbauer, Wolfgang (SP) <
>      > >> wolfgang.viechtbauer using maastrichtuniversity.nl
>     <mailto:wolfgang.viechtbauer using maastrichtuniversity.nl>> wrote:
>      > >>
>      > >>> Hi All,
>      > >>>
>      > >>> Let's say there are two packages pkgA and pkgB, both of which
>     have a
>      > >>> generic function
>      > >>>
>      > >>> foo <- function(x, ...)
>      > >>>     UseMethod("foo")
>      > >>>
>      > >>> and pkgA has a method for objects of class "A":
>      > >>>
>      > >>> foo.A <- function(x, ...)
>      > >>>     print(x)
>      > >>>
>      > >>> and pkgB has a method for objects of class "B":
>      > >>>
>      > >>> foo.B <- function(x, ...)
>      > >>>     plot(x)
>      > >>>
>      > >>> Both packages export foo and their method and declare their
>     respective
>      > S3
>      > >>> methods, so:
>      > >>>
>      > >>> export(foo)
>      > >>> export(foo.A)
>      > >>> S3method(foo, A)
>      > >>>
>      > >>> in NAMESPACE of pkgA and
>      > >>>
>      > >>> export(foo)
>      > >>> export(foo.B)
>      > >>> S3method(foo, B)
>      > >>>
>      > >>> in NAMESPACE of pkgB.
>      > >>>
>      > >>> If a user loads pkgA first and then pkgB, this fails:
>      > >>>
>      > >>> library(pkgA)
>      > >>> library(pkgB)
>      > >>> x <- 1:4
>      > >>> class(x) <- "A"
>      > >>> foo(x)
>      > >>>
>      > >>> Error in UseMethod("foo") :
>      > >>>    no applicable method for 'foo' applied to an object of
>     class "A"
>      > >>>
>      > >>> and vice-versa. Of course, pkgA::foo(x) works. Aside from pkgA
>      > importing
>      > >>> foo() or vice-versa, is there some other clever way to make
>     this work?
>      > In
>      > >>> earlier versions of R (at least in 3.6.3), this used to work
>     (i.e., the
>      > >>> generic foo() from pkgB would find method foo.A() and
>     vice-versa), but
>      > >> not
>      > >>> since 4.0.0.
>      > >>>
>      > >>> Best,
>      > >>> Wolfgang
>      > >>>
>      > >>> ______________________________________________
>      > >>> R-package-devel using r-project.org
>     <mailto:R-package-devel using r-project.org> mailing list
>      > >>> https://stat.ethz.ch/mailman/listinfo/r-package-devel
>      > >>>
>      > >>
>      > >>          [[alternative HTML version deleted]]
>      > >>
>      > >> ______________________________________________
>      > >> R-package-devel using r-project.org
>     <mailto:R-package-devel using r-project.org> mailing list
>      > >> https://stat.ethz.ch/mailman/listinfo/r-package-devel
>      > >>
>      > >
>      > >       [[alternative HTML version deleted]]
>      > >
>      > > ______________________________________________
>      > > R-package-devel using r-project.org
>     <mailto:R-package-devel using r-project.org> mailing list
>      > > https://stat.ethz.ch/mailman/listinfo/r-package-devel
>      > >
>      >
>      > ______________________________________________
>      > R-package-devel using r-project.org
>     <mailto:R-package-devel using r-project.org> mailing list
>      > https://stat.ethz.ch/mailman/listinfo/r-package-devel
>      >
> 
>              [[alternative HTML version deleted]]
> 
>     ______________________________________________
>     R-package-devel using r-project.org <mailto: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