[Rd] S3 dispatch does not work for generics defined inside an environment

Joshua Ulrich jo@h@m@u|r|ch @end|ng |rom gm@||@com
Wed Jun 30 12:39:17 CEST 2021


On Wed, Jun 30, 2021 at 5:17 AM Duncan Murdoch <murdoch.duncan using gmail.com> wrote:
>
> On 30/06/2021 5:22 a.m., Taras Zakharko wrote:
> > Dear all,
> >
> > I have a generic function and a bunch of methods defined in a separate environment. Here is a reduced example:
> >
> >     env <- local({
> >       # define the generic function and the method
> >       myfun <- function(x) UseMethod("myfun")
> >       myfun.myclass <- function(x) print("called myfun.myclass”)
> >
> >       # register the method
> >       .S3method("myfun", "myclass", myfun.myclass)
> >
> >       environment()
> >    })
> >
> > Since the method has been registered, I hoped that invocation like this would work:
> >
> >     env$myfun(structure(0, class = "myclass”))
> >
> > However, this results in a “no applicable method" error.
> >
> > It is my understanding that registerS3method (called by .S3method) will install the method string in the .__S3MethodsTable__. table of the environment where the generic function is defined, and this table is subsequently used by usemethod() inside R, so I am puzzled that the dispatch does not work. I checked and the  .__S3MethodsTable__. of env is indeed setup correctly. I also tried manually adding the method string to the global .__S3MethodsTable__. inside .BaseNamespaceEnv to no effect.
> >
> > In fact, the only way to make it work is to define either myfun or  myfun.myclas in the global environment, which is something I would like to avoid.
> >
> > Thank you in advance for any pointers!
> >
>
> registerS3method has an additional parameter "envir" which I believe
> would end up set to env in your code.  So this works:
>
>  > eval(expression(myfun(structure(0, class = "myclass"))), envir = env)
> [1] "called myfun.myclass"
>
> You could probably also call registerS3method with envir specified
> appropriately and get your original expression to work.
>
That doesn't seem to work on 4.1.0 for me. The code below worked for
me in Oct-2020, though I'm not sure what version of R I was using at
the time. I was slow to upgrade to 4.0, so it was probably the latest
3.x version.

env <- new.env()
local({
   # define the generic function and the method
   myfun <- function(x) { UseMethod("myfun", x) }

   # register the method
   registerS3method("myfun", "myclass",
       function(x) { print("called myfun.myclass") },
       envir = env)
}, envir = env)
attach(env)
myfun(structure(0, class = "myclass"))


> Duncan Murdoch
>
> ______________________________________________
> R-devel using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



-- 
Joshua Ulrich  |  about.me/joshuaulrich
FOSS Trading  |  www.fosstrading.com



More information about the R-devel mailing list