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

CCing r-devel.

On Tue, 14 May 2019 at 02:11, Pavel Krivitsky <pavel at uow.edu.au> wrote:
>
> Dear All,
>
> I've run into this while updating a package with unfortunately named
> legacy functions. It seems like something that might be worth changing
> in R, and I want to get a sense of whether this is a problem before
> submitting a report to the Bugzilla.
>
> It appears that the 3-argument form of S3method() in NAMESPACE controls
> dispatching when the generic is called from outside the package that
> defines it but not when it's called from inside the package that
> defines it.
>
> For example the attached minimal package has four R functions:
>
>    gen <- function(object, ...)
>      UseMethod("gen")
>
>    .gen.formula <- function(object, ...){
>      message("I am the S3method-declared method.")
>    }
>
>    gen.formula <- function(object, ...){
>      message("I am the function with an unfortunate name.")
>    }
>
>    test_me <- function(){
>      message("I am the tester. Which one will I call?")
>      gen(a~b)
>    }
>
> and the following NAMESPACE:
>
>    export(gen)
>    S3method(gen, formula, .gen.formula)
>    export(gen.formula)
>    export(test_me)
>
> Now,
>
>    library(anRpackage)
>    example(test_me)
>
> results in the following:
>
>    test_m> test_me
>    function(){
>      message("I am the tester. Which one will I call?")
>      gen(a~b)
>    }
>    <bytecode: 0x562fb9d32d68>
>    <environment: namespace:anRpackage>
>
>    test_m> test_me() # Calls gen.formula()
>    I am the tester. Which one will I call?
>    I am the function with an unfortunate name.
>
>    test_m> gen(a~b) # Calls .gen.formula()
>    I am the S3method-declared method.
>
> So, calling the same generic function with the same class results in
> different dispatching behaviour depending on whether the call is from
> within the package doing the export or from the outside.

It does not depend on whether you export gen.formula() or not. When
you call gen() inside your package, the S3 dispatch mechanism finds a
method gen.formula defined in that environment (the package's
namespace), so it is called.

> This behaviour appears to be as documented (
> https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Method-dispatching
> ), but it seems to me that if S3method() is allowed to give the name of
> the method to be used, then it should should override the name-based
> dispatching both inside and outside the package.
>
> Any thoughts?

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. I don't think that's a good idea.

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?=