From |uc@r @end|ng |rom |edor@project@org  Tue May 14 12:50:40 2019
From: |uc@r @end|ng |rom |edor@project@org (=?UTF-8?Q?I=C3=B1aki_Ucar?=)
Date: Tue, 14 May 2019 12:50:40 +0200
Subject: [Rd] [R-pkg-devel] Three-argument S3method declaration does not
 seem to affect dispatching from inside the package.
In-Reply-To: <14d531d671791b51683b71ee0eece1c9a29c374d.camel@uow.edu.au>
References: <49d473a1bfa29f95d74f931ecfdc2a6b346ca6a2.camel@uow.edu.au>
 <CALEXWq058Wg0oskeaFAjPdptTEjVMWLFbUr+FeBwdKwP93T=Kw@mail.gmail.com>
 <14d531d671791b51683b71ee0eece1c9a29c374d.camel@uow.edu.au>
Message-ID: <CALEXWq02kZdw79BWJiAtj-HXMnCeX_PRF_yFTT6DpNCn=MxPAw@mail.gmail.com>

On Tue, 14 May 2019 at 12:31, Pavel Krivitsky <pavel at uow.edu.au> wrote:
>
> > Note that disabling name-based dispatch implies two things: 1) the
> > inability to override your method by defining gen.formula in the
> > global environment, and 2) another package can break yours (i.e.,
> > internal calls to gen()) by registering an S3 method for gen() after
> > you.
>
> That's a good point.
>
>    > library(anRpackage)
>    > gen(a~b)
>    I am the S3method-declared method.
>    > gen.formula <- function(object, ...){message("I am the externally declared method.")}
>    > gen(a~b)
>    I am the externally declared method.
>    > test_me()
>    I am the tester. Which one will I call?
>    I am the function with an unfortunate name.
>
> In that case, I think that the least surprising behaviour would
> prioritise declarations and methods "nearer" to the caller over those
> "farther" from the caller (where "caller" is the caller of the generic,
> not the generic itself), and, within that, give precedence to S3method
> declarations over function names.

The thing is that, in R, "nearer" means "the calling environment" (and
then, other things). When you call test_me(), the calling environment
for gen() is the package namespace. When you call gen() directly, then
the calling environment is the global environment. So what happens
here follows the principle of least astonishment.

The issue here is that you are registering a non-standard name
(.gen.formula) for that generic and then defining what would be the
standard name (gen.formula) for... what purpose? IMHO, this is a bad
practice and should be avoided.

> That is, for a call from inside a package, the order of precedence
> would be as follows:
>    1. S3method() in that package's NAMESPACE.
>    2. Appropriately named function in that package (exported or not).
>    3. Appropriately named function in calling environment (which may be
>       GlobalEnv).
>    4. S3method() in other loaded packages' NAMESPACEs.
>    5. Appropriately named functions exported by other loaded packages'
>       NAMESPACEs.
>
> For a call from outside a package, the precedence is the same, but 1
> and 2 are not relevant.
>
> As far as I can tell, this is the current behaviour except for the
> relative ordering of 1 and 2.

Nope. Current behaviour (see details in ?UseMethod) is:

"To support this, UseMethod and NextMethod search for methods in two
places: in the environment in which the generic function is called,
and in the registration data base for the environment in which the
generic is defined".

Changing this would probably break a lot of things out there.

I?aki



[Rd] [R-pkg-devel] Three-argument S3method declaration does not seem to affect dispatching from inside the package.
=?UTF-8?Q?I=C3=B1aki_Ucar?=