[R-pkg-devel] A function in one of my package is now a method in base R

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Fri Aug 2 20:43:20 CEST 2024


On 2024-08-02 10:35 a.m., Shu Fai Cheung wrote:
> Hi All,
> 
> I have a function (not a method), sort_by(), in one of my packages. A
> new method with the same name was introduced in the recent versions of
> R (4.4.0 or 4.4.1, I forgot which one), resulting in potential
> conflict in users' code.
> 
> Certainly, users can simply use pkg_name::function_name() to solve the
> conflict. However, I would like to be consistent with base R and so I
> am thinking about converting my function to a method for the class for
> which my function is intended to work on (e.g, est_table).
> 
> However, my function has arguments different from those in the base R sort_by():
> 
> Base R:
> 
> sort_by(x, y, ...)
> 
> My function:
> 
> sort_by(
>    object,
>    by = c("op", "lhs", "rhs"),
>    op_priority = c("=~", "~", "~~", ":=", "~1", "|", "~*~"),
>    number_rows = TRUE
> )
> 
> If I write the function sort_by.est_table(), I would need to match the
> argument names of the base R sort_by(). However, I think it is a bad
> idea to rename the arguments in my function and it will break existing
> code.
> 
> Any suggestions on how I should proceed? Is keeping my function as-is
> a better option? Name conflict is not unusual across packages and so
> users need to learn how to solve this problem anyway. Nevertheless, if
> possible, I would like to solve the conflict internally such that
> users do not need to do anything.

I think it's impossible to avoid some inconvenience to your users.

Here's what I'd suggest:

- Create a method for base::sort_by(), as you suggested you could.  Use 
the generic's variable names for compatibility, but also add your extra 
variable names as additional arguments, e.g.

  sort_by.est_table <- function(x, y, object,
    by = c("op", "lhs", "rhs"),
    op_priority = c("=~", "~", "~~", ":=", "~1", "|", "~*~"),
    number_rows = TRUE, ...) {

   # This test seems unlikely:  how would we have dispatch here if we 
specified object explicitly?

   if (!missing(object) {
     if (!missing(x))
       stop("both x and object specified!")
     x <- object
   }

   # This one is more likely to do something:

   if (!missing(by)) {
     if (!missing(y))
       stop("both y and by specified!")
     y <- by
   }

   # Now proceed using x and y

   ...
}

- Create a separate function, e.g. sort_by_old() which is exactly 
compatible with your old sort_by().  For users where the above doesn't 
just work, they can switch to sort_by_old().

Duncan Murdoch



More information about the R-package-devel mailing list