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