The problem is that there's no way to declare that an internal function should or shouldn't be treated as an S3 method, other than by declaring it as one in NAMESPACE and exporting it. If you read the thread "Unfortunate function name generic.something​" that started last week, you'll see the opposing problem to yours: a local function named levels.no that isn't intended to be an S3 method, but will be treated as one in some circumstances.

You do export emm_basis and recover_data, so those generics are available to users. And you do declare some of the methods, e.g. in emmeans 1.8.5, users can see methods for some classes:

> methods("emm_basis")
[1] emm_basis.aovlist* emm_basis.lm* emm_basis.lme* emm_basis.merMod* emm_basis.mlm*

As the message below says, you don't declare emm_basis.Gam to be a method, which means that a user with a Gam object who calls emm_basis will get the default method instead, whereas when code in your package calls it, they'll get the Gam method.

You say users should never call emm_basis directly, but package developers should provide methods for it. At a minimum that's going to make debugging those packages much more confusing. And if they have a class which inherits from Gam and want to call the inherited method, they won't get it.

So I think in this case the NOTE is something you should fix.

Duncan Murdoch

On 10/05/2023 10:49 p.m., Lenth, Russell V wrote:
Dear R package developers

My emmeans package failed preliminary checks when I submitted an update today, 
apparently due to a recent change in requirements on method registration. The 
message I got was:

* checking S3 generic/method consistency ... NOTE
Apparent methods for exported generics not registered:
   emm_basis.Gam emm_basis.MCMCglmm emm_basis.averaging
   emm_basis.betareg emm_basis.brmsfit emm_basis.carbayes emm_basis.clm
   emm_basis.clmm emm_basis.coxme emm_basis.coxph emm_basis.default
   emm_basis.gam emm_basis.gamlss emm_basis.gamm emm_basis.gee
   emm_basis.geeglm emm_basis.geese emm_basis.gls emm_basis.gnls
   emm_basis.hurdle emm_basis.lqm emm_basis.lqmm emm_basis.mblogit
   emm_basis.mcmc emm_basis.mcmc.list emm_basis.mira emm_basis.mmer
   emm_basis.multinom emm_basis.nlme emm_basis.nls emm_basis.polr
   emm_basis.qdrg emm_basis.rms emm_basis.rq emm_basis.rqs
   emm_basis.stanreg emm_basis.survreg emm_basis.svyolr
   emm_basis.zeroinfl recover_data.MCMCglmm recover_data.averaging
   recover_data.betareg recover_data.brmsfit recover_data.carbayes
   recover_data.clm recover_data.clmm recover_data.coxme
   recover_data.coxph recover_data.default recover_data.gam
   recover_data.gamlss recover_data.gamm recover_data.gee
   recover_data.geeglm recover_data.geese recover_data.gls
   recover_data.gnls recover_data.hurdle recover_data.lqm
   recover_data.lqmm recover_data.manova recover_data.mblogit
   recover_data.mcmc recover_data.mcmc.list recover_data.mira
   recover_data.mmer recover_data.multinom recover_data.nlme
   recover_data.nls recover_data.polr recover_data.qdrg recover_data.rms
   recover_data.rq recover_data.rqs recover_data.stanreg
   recover_data.survreg recover_data.svyglm recover_data.svyolr
   recover_data.zeroinfl
See section 'Registering S3 methods' in the 'Writing R Extensions'
manual.

I guess my question is "why does this matter?" There are many, many functions 
mentioned here, but they are all methods for emm_basis and recover_data. Both generics 
are in the emmeans namespace, as are all these functions.

The section on registering S3 methods explains:

The standard method for S3-style UseMethod dispatching might fail to locate 
methods defined in a package that is imported but not attached to the search 
path. To ensure that these methods are available the packages defining the 
methods should ensure that the generics are imported and register the methods 
using S3method directives...

But clearly all those methods flagged in the messages will be found in the same 
namespace as the generics -- emm_basis and recover_data -- so not being able to 
find them is not an issue. Moreover, emm_basis() and recover_data() are not 
meant to be called directly by a user, or even by code in another package. They 
are only meant to be called within the function emmeans::ref_grid(), and the 
existence of those generics and methods is simply a mechanism for being able to 
support a lot of different model classes.

Obviously, I could add a whole lot of S3method() directives to the NAMESPACE 
file, but it just seems wasteful to export all those methods when they are 
never needed outside the emmeans namespace.

Am I missing something?

Thanks

Russ Lenth



        [[alternative HTML version deleted]]

______________________________________________
R-package-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel

______________________________________________
R-package-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel

Reply via email to