Is it possible to dispatch S3 methods based on the class of an argument specified by its position only?

Viewed 153

Imagine we have the following S3 generic that we want to dispatch using the class of the first argument:

genfun <- function(x, ...) UseMethod("genfun", x)

Let's now consider a numeric method for this generic:

genfun.numeric <- function(x, y) {
  x[y]
}

The following call works just perfectly well:

genfun(1:5, 3)

Of note, it appears that the names of the arguments of the method do not need to match those of the generic. Indeed, if we define the numeric method this way:

genfun.numeric <- function(a, b) {
  a[b]
}

It also works:

genfun(1:5, 3)

However, the following call fails:

genfun(a = 1:5, b = 3)

whereas, if we return to the first definition of the method that match the arguments' names of the generic:

genfun.numeric <- function(x, y) {
  x[y]
}

a call with named arguments works just fine:

genfun(x = 1:5, y = 3)

or:

genfun(y = 3, x = 1:5)

Is there a way to make the method definition based on arguments a and b also work when called with named argument?

1 Answers

Yes, there is. Define the generic without arguments other than the dots argument.

genfun <- function(...) UseMethod("genfun")

Now both methods work with or without named arguments.

genfun.numeric <- function(x, y) {
  x[y]
}

genfun(1:5, 3)
#[1] 3

And the other one.

genfun.numeric <- function(a, b) {
  a[b]
}

genfun(1:5, 3)
#[1] 3

genfun(a = 1:5, b = 3)
#[1] 3
Related