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

2020-06-22 Thread Bert Gunter
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

2020-06-22 Thread luke-tierney

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

2020-06-22 Thread Bert Gunter
"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

2020-06-22 Thread Mark Leeds
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

2020-06-22 Thread Duncan Murdoch

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

2020-06-22 Thread Tom Wainwright
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

2020-06-22 Thread Neal Fultz
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

2020-06-22 Thread Duncan Murdoch

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

2020-06-22 Thread Bert Gunter
...
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

2020-06-22 Thread Duncan Murdoch

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

2020-06-22 Thread Viechtbauer, Wolfgang (SP)
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