[R-pkg-devel] Unfortunate function name generic.something

Ulrike Groemping u|r|ke@groemp|ng @end|ng |rom bht-ber||n@de
Tue May 9 08:13:22 CEST 2023


Am 09.05.2023 um 01:23 schrieb Duncan Murdoch:
> On 08/05/2023 6:58 p.m., Simon Urbanek wrote:
>>
>>
>>> On 8/05/2023, at 11:58 PM, Duncan Murdoch <murdoch.duncan using gmail.com> 
>>> wrote:
>>>
>>> There really isn't such a thing as "a function that looks like an S3 
>>> method, but isn't".  If it looks like an S3 method, then in the 
>>> proper circumstances, it will be called as one.
>>>
>>
>>
>> I disagree - that was the case in old versions, but not anymore. The 
>> whole point of introducing namespaces and method registration was to 
>> make it clear when a function is a method and when it is a function. 
>> If you export a function it won't be treated as a method:
>>
>> In a package NAMESPACE:
>> export(foo.cls)
>> package R code: foo.cls <- function(x) "foo.cls"
>>
>> in R:
>>> cls=structure(1,class="cls")
>>> foo=function(x) UseMethod("foo")
>>> foo(cls)
>> Error in UseMethod("foo") :
>>    no applicable method for 'foo' applied to an object of class "cls"
>>> foo.cls(cls)
>> [1] "foo.cls"
>>
>> So R knows very well what is a method and what is a function. If you 
>> wanted it to be a method, you have to use S3method(foo, cls) and that 
>> **is** different from export(foo.cls) - quite deliberately so.
>
> That is true for package users, but it's not true within the package.  
> I just tested this code in a package:
>
>   levels.no <- function(xx, ...) {
>     stop("not a method")
>   }
>
>   f <- function() {
>     x <- structure(1, class = "no")
>     levels(x)
>   }
>
> Both levels.no and f were exported.  If I attach the package and call 
> f(), I get the error
>
>   > library(testpkg)
>   > f()
>   Error in levels.no(x) : not a method
>
> because levels.no is being treated as a method when levels() is called 
> in the package.
>
> If I create an x like that outside of the package and call levels(x) 
> there, I get NULL, because levels.no is not being treated as a method 
> in that context.
>
> As far as I know, there is no possible way to have a function in a 
> package that is called "levels.no" and not being treated as a method 
> within the package.  I don't think there's any way to declare "this is 
> not a method", other than naming it differently.
>
> Duncan

Before the current check notes, I did not think about that problem. I 
think that it is quite unlikely to hit a user of mine, because the 
package calls levels() in a few places on columns of designs only. I 
still think that it should remain possible to have an *internal* 
function that is named in whatever way I like it named (I would of 
course not choose that name now, but it's there, and it would break a 
lot of my own non-package code if I changed it in the package). My 
current "fix" made the problem worse.
Would it have been permissible to not register the function ? I could 
then revert to not registering it, but keeping the error message in 
place, just in case the unlikely event happens.

Ulrike

>
>>
>> Cheers,
>> Simon
>>
>>
>>> In your case the function name is levels.no, and it isn't exported.  
>>> So if you happen to have an object with a class inheriting from 
>>> "no", and you call levels() on it, levels.no might be called.
>>>
>>> This will only affect users of your package indirectly.  If they 
>>> have objects inheriting from "no" and call levels() on them, 
>>> levels.no will not be called.  But if they pass such an object to 
>>> one of your package functions, and that function calls levels() on 
>>> it, they could end up calling levels.no(). It all depends on what 
>>> other classes that object inherits from.
>>>
>>> You can test this yourself.  Set debugging on any one of your 
>>> functions, then call it in the normal way.  Then while still in the 
>>> debugger set debugging on levels.no, and create an object using
>>>
>>>   x <- structure(1, class = "no")
>>>
>>> and call levels(x).  You should break to the code of levels.no.
>>>
>>> That is why the WRE manual says "First, a caveat: a function named 
>>> gen.cl will be invoked by the generic gen for class cl, so do not 
>>> name functions in this style unless they are intended to be methods."
>>>
>>> So probably the best solution (even if inconvenient) is to rename 
>>> levels.no to something that doesn't look like an S3 method.
>>>
>>> Duncan Murdoch
>>>
>>> On 08/05/2023 5:50 a.m., Ulrike Groemping wrote:
>>>> Thank your for the solution attempt. However, using the keyword 
>>>> internal
>>>> does not solve the problem, the note is still there. Any other 
>>>> proposals
>>>> for properly documenting a function that looks like an S3 method, 
>>>> but isn't?
>>>> Best, Ulrike
>>>> Am 05.05.2023 um 12:56 schrieb Iris Simmons:
>>>>> You can add
>>>>>
>>>>> \keyword{internal}
>>>>>
>>>>> to the Rd file. Your documentation won't show up the in the pdf
>>>>> manual, it won't show up in the package index, but you'll still be
>>>>> able to access the doc page with ?levels.no <http://levels.no> or
>>>>> help("levels.no <http://levels.no>").
>>>>>
>>>>> This is usually used in a package's deprecated and defunct doc pages,
>>>>> but you can use it anywhere.
>>>>>
>>>>> On Fri, May 5, 2023, 06:49 Ulrike Groemping
>>>>> <ulrike.groemping using bht-berlin.de> wrote:
>>>>>
>>>>>      Dear package developeRs,
>>>>>
>>>>>      I am working on fixing some notes regarding package DoE.base.
>>>>>      One note refers to the function levels.no <http://levels.no> and
>>>>>      complains that the
>>>>>      function is not documented as a method for the generic function
>>>>>      levels.
>>>>>      Actually, it is not a method for the generic levels, but a 
>>>>> standalone
>>>>>      internal function that I like to have documented.
>>>>>
>>>>>      Is there a way to document the function without renaming it and
>>>>>      without
>>>>>      triggering a note about method documentation?
>>>>>
>>>>>      Best, Ulrike
>>>>>
>>>>>      --
>>>>>      ##############################################
>>>>>      ## Prof. Ulrike Groemping
>>>>>      ## FB II
>>>>>      ## Berliner Hochschule für Technik (BHT)
>>>>>      ##############################################
>>>>>      ## prof.bht-berlin.de/groemping 
>>>>> <http://prof.bht-berlin.de/groemping>
>>>>>      ## Phone: +49(0)30 4504 5127
>>>>>      ## Fax:   +49(0)30 4504 66 5127
>>>>>      ## Home office: +49(0)30 394 04 863
>>>>>      ##############################################
>>>>>
>>>>>      ______________________________________________
>>>>>      R-package-devel using r-project.org mailing list
>>>>>      https://stat.ethz.ch/mailman/listinfo/r-package-devel
>>>>>
>>>> ______________________________________________
>>>> R-package-devel using r-project.org mailing list
>>>> https://stat.ethz.ch/mailman/listinfo/r-package-devel
>>>
>>> ______________________________________________
>>> R-package-devel using r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-package-devel
>>>
>>
>



More information about the R-package-devel mailing list