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

On Sat, 18 May 2019 at 23:34, Pavel Krivitsky <pavel at uow.edu.au> wrote:
>
> > 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.
>
> The situation initially arose when I wanted to soft-deprecate calling a
> particular method by its full name in order to clean up the package's
> namespace.
>
> To use our working example, I wanted calls to gen.formula() to issue a
> deprecation warning, but calls to gen(formula) not to. The simplest way
> to do that that I could find was to create a function, say,
> .gen.formula() that would implement the method and declare it as the S3
> export, and modify gen.formula() to issue the warning before passing on
> to .gen.formula(). Then, direct calls to gen.formula() would produce a
> warning, but gen(formula) would by pass it.

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

> > > 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".
>
> Can you be more specific where the sequence above contradicts the
> current implementation (except for swapping 1 and 2)? As far as I can
> tell, it's just a more concrete description of what's in the
> documentation.

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.

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