Re: [R-pkg-devel] [External] Re: Two packages with the same generic function
OK. Thanks. Bert Gunter On Mon, Jun 22, 2020 at 7:51 PM wrote: > On Tue, 23 Jun 2020, Bert Gunter wrote: > > > "Users don't get warned about overriding names in packages they've > > loaded, because that would just be irritating." > > All Duncan is saying is that you don't get a notification if you do > > mean <- log > > in the interpreter. If you attach a package that does this you would > get a notification (or an error if you configure your conflict > resolution options appropriately). > > Best, > > luke > > > > > 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? > > > > > > 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 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.dun...@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 > >>> 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.viechtba...@maastrichtuniversity.nl> wrote: > > > >> Hi All, > >> >
Re: [R-pkg-devel] [External] Re: Two packages with the same generic function
On Tue, 23 Jun 2020, Bert Gunter wrote: "Users don't get warned about overriding names in packages they've loaded, because that would just be irritating." All Duncan is saying is that you don't get a notification if you do mean <- log in the interpreter. If you attach a package that does this you would get a notification (or an error if you configure your conflict resolution options appropriately). Best, luke 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? 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 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 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 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.viechtba...@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 wor
Re: [R-pkg-devel] Two packages with the same generic function
"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? 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 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 > 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 > > 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.viechtba...@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) > > >>> expor
Re: [R-pkg-devel] Two packages with the same generic function
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 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 > 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.viechtba...@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@r-project.org mailing list > >>> https://
Re: [R-pkg-devel] Two packages with the same generic function
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 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.viechtba...@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@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel [[alternative HTML version deleted]] __ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel [[alternative HTML version deleted]] __ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel __ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
Re: [R-pkg-devel] Two packages with the same generic function
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.) 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 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.viechtba...@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@r-project.org mailing list > > https://stat.ethz.ch/mailman/listinfo/r-package-devel > > > > [[alternative HTML version deleted]] > > __ > R-package-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-package-devel > [[alternative HTML version deleted]] __ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
Re: [R-pkg-devel] Two packages with the same generic function
Another decent alternative is to submit the generic function to the `generics` package - https://github.com/r-lib/generics - or create your own API package. Both package A and B can import the generic from it, and everything works fine. It may also reduce your dependencies and/or build time. This is much simpler than the workarounds we had tried to optionally allow use of tidy() from DeclareDesign without transitively importing the entire tidyverse, for example. We had tried various ways of delegating from pkgA::foo.default to pkgB::foo but it had some edge cases around the order that the user attached the packages IIRC. On Mon, Jun 22, 2020 at 11:01 AM Duncan Murdoch wrote: > > On 22/06/2020 1:40 p.m., Bert Gunter 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? > > It's always possible to make a new name, e.g. > > fooA <- pkgA::foo > fooB <- pkgB::foo > > If you are writing a package, this can be done in the NAMESPACE file, e.g. > > importFrom(pkgA, fooA = foo) > > though this doesn't appear to be documented in the usual places. > > 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 10:00 AM Viechtbauer, Wolfgang (SP) < > > wolfgang.viechtba...@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@r-project.org mailing list > >> https://stat.ethz.ch/mailman/listinfo/r-package-devel > >> > > > > [[alternative HTML version deleted]] > > > > __ > > R-package-devel@r-project.org mailing list > > https://stat.ethz.ch/mailman/listinfo/r-package-devel > > > > __ > R-package-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-package-devel __ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
Re: [R-pkg-devel] Two packages with the same generic function
On 22/06/2020 1:40 p.m., Bert Gunter 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? It's always possible to make a new name, e.g. fooA <- pkgA::foo fooB <- pkgB::foo If you are writing a package, this can be done in the NAMESPACE file, e.g. importFrom(pkgA, fooA = foo) though this doesn't appear to be documented in the usual places. 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 10:00 AM Viechtbauer, Wolfgang (SP) < wolfgang.viechtba...@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@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel [[alternative HTML version deleted]] __ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel __ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
Re: [R-pkg-devel] Two packages with the same generic function
... 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.viechtba...@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@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-package-devel > [[alternative HTML version deleted]] __ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
Re: [R-pkg-devel] Two packages with the same generic function
On 22/06/2020 1:00 p.m., Viechtbauer, Wolfgang (SP) 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) Wouldn't the user have got a warning at this point about pkgB::foo masking pkgA::foo? 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. Can't one of the packages import the generic from the other package, and then declare the method as a method of that other generic? That seems like the only thing that would make sense. There's no reason to believe that pkgA::foo has anything whatsoever to do with pkgB::foo without this. Duncan Murdoch __ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
[R-pkg-devel] Two packages with the same generic function
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@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel