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

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Wed Jun 30 12:17:04 CEST 2021


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.

Duncan Murdoch



More information about the R-devel mailing list