On Sun, 19 May 2019 at 23:23, Pavel Krivitsky <pa...@uow.edu.au> wrote: > > Hi, Inaki, > > On Sun, 2019-05-19 at 16:59 +0200, Iñaki Ucar wrote: > > IMO the simplest way to do this is to check who the caller was: > > > > foo <- function(x) UseMethod("foo") > > foo.bar <- function(x) { > > sc <- sys.call(-1) > > if (is.null(sc) || sc[[1]] != "foo") > > .Deprecated(msg="Calling 'foo.bar' directly is deprecated") > > } > > > > x <- 1 > > class(x) <- "bar" > > > > foo(x) # silent > > foo.bar(x) # a warning is issued > > f <- getS3method("foo","bar") > f(x) # spurious warning > > foo.baz <- function(x) NextMethod("foo") > class(x) <- c("baz","bar") > foo(x) # spurious warning
Checking the enclosing environment and whether was called through NextMethod respectively covers these cases too. > > The description in the documentation means that point 3) in your list > > goes always first, which automatically implies 2) if the generic is > > defined in the same package. > > Are you sure which package defines the generic matters? I've just ran > some tests with two packages and moving the generic around doesn't seem > to affect things: the calling function determines whose method is used. If package A defines generic foo and package B defines method foo.bar without registering nor exporting it, then foo can't find foo.bar. > It seems to me like there is no contradiction after all, except that I > propose that the registered method should take precedence within a > namespace. > > The only situation in which it would change R's behaviour would be when > a package/namespace contains a function foo.bar() AND a NAMESPACE > containing S3method(foo,bar,not.foo.bar) AND calls foo() on objects of > type bar from inside the package. It is extremely unlikely to break any > existing code. To try to avoid changing current behaviour if foo.bar is found, R would need to check whether the enclosing environment is identical to the enclosing environment of the registered method, and in that case, give precedence to the latter (which, BTW, is exactly what you need to do to fix the first spurious warning above). And still, funny things may happen. For example, pkgA defines generic foo, exports foo.bar and registers other.foo.bar instead of foo.bar. Following your proposal, if I load pkgA and call foo for an object of class bar, other.foo.bar is called. Then I load pkgB, which registers just another method for foo.bar, and call foo again. What happens is that the registered method belongs now to pkgB, which is a different namespace, so we got different precedence, and foo.bar is called instead. Exceptions leads us to inconsistencies like this. I can't speak for R core, but I don't think that the use case is compelling enough to take that path. Iñaki ______________________________________________ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel