How can I add additional arguments to methods for internal generics? How can I add additional arguments to methods for internal generics? r r

How can I add additional arguments to methods for internal generics?


I don't see an easy way around this except to strip the class (which makes a copy of x)

`[<-.myClass` <- function(x, i, value, ..., foo = TRUE) {  if (foo) {    cat("hi!")    x  } else {    class_x <- class(x)    x <- unclass(x)    x[i] <- value    class(x) <- class_x    x  }}x <- structure(1:2, class = "myClass")x[1] <- 3#> hi!x[1, foo = FALSE] <- 3x#> [1] 3 2#> attr(,"class")#> [1] "myClass"

This is not a general approach - it's only needed for [, [<-, etc because they don't use the regular rules for argument matching:

Note that these operations do not match their index arguments in the standard way: argument names are ignored and positional matching only is used. So m[j = 2, i = 1] is equivalent to m[2, 1] and not to m[1, 2].

(from the "Argument matching" section in ?`[`)

That means your x[1, foo = FALSE] is equivalent to x[1, FALSE] and then you get an error message because x is not a matrix.

Approaches that don't work:

  • Supplying additional arguments to NextMethod(): this can only increase the number of arguments, not decrease it

  • Unbinding foo with rm(foo): this leads to an error about undefined foo.

  • Replacing foo with a missing symbol: this leads to an error that foo is not supplied with no default argument.


Here's how I understand it, but I don't know so much about that subject so I hope I don't say too many wrong things.

From ?NextMethod

NextMethod invokes the next method (determined by the class vector, either of the object supplied to the generic, or of the first argument to the function containing NextMethod if a method was invoked directly).

Your class vector is :

x <- c(1,2)class(x) <- "myClass" # note: you might want class(x) <- c("myClass", class(x))class(x) # [1] "myClass"

So you have no "next method" here, and [<-.default, doesn't exist.

What would happen if we define it ?

`[<-.default` <- function(x, i, j, value, ...) {print("default"); value} x[1, foo = FALSE] <- 3 # [1] "default"x# [1] 3

If there was a default method with a ... argument it would work fine as the foo argument would go there, but it's not the case so I believe NextMethod just cannot be called as is.

You could do the following to hack around the fact that whatever is called doesn't like to be fed a foo argument:

`[<-.myClass` <- function(x, i, j, value, foo = FALSE, ...) {  if (foo) {    stop("'foo' must be false!")  }  `[<-.myClass` <- function(x, i, j, value, ...) NextMethod()  args <- as.list(match.call())[-1]  args <- args[names(args) %in% c("","x","i","j","value")]  do.call("[<-",args)}x[1, foo = FALSE] <- 3x# [1] 3 2# attr(,"class")# [1] "myClass"

Another example, with a more complex class :

library(data.table)x        <- as.data.table(iris[1:2,1:2])class(x) <- c("myClass",class(x))x[1, 2, foo = FALSE] <- 9999#    Sepal.Length Sepal.Width# 1:          5.1        9999# 2:          4.9           3class(x)# [1] "myClass"    "data.table" "data.frame"

This would fail if the next method had other arguments than x, i, j and value, in that case better to be explicit about our additional arguments and run args <- args[! names(args) %in% c("foo","bar")]. Then it might work (as long as arguments are given explicitly as match.call doesn't catch default arguments). I couldn't test this though as I don't know such method for [<-.