Marc Choisy
Marc Choisy

Reputation: 141

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

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?

Upvotes: 3

Views: 260

Answers (1)

Rui Barradas
Rui Barradas

Reputation: 76683

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

Upvotes: 1

Related Questions