[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