bricx
bricx

Reputation: 663

S3 generic/method consistency - How to dispatch according to chosen type?

I am trying to build a generic function that dispatches to other functions according to the type of algorithm chosen. In the example below, the type of algorithm is just chosen by a character like "algo1", "algo2", etc... x is an object of class S4. Arguments A & B are common to all methods (functions). I'd like to name the functions called Myfun.algo1 and Myfun.algo2. These functions have some parameters set to some default value, hence the purpose of having a generic.

#' @export Myfun
Myfun<-function(x, type = c("algo1", "algo2"), A, B, ...){

  switch(type,

         algo1={res<-do.call(Myfun.algo1, list(x, A, B, ...))},

         algo2={res<-do.call(Myfun.algo2, list(x, A, B, ...))},

         stop("Unknown Type"))

   return(res)
}


#' @rdname MyFun
#' @export
MyFun.algo1<-function(x, A, B, C=2, D=300){

 #Do a bit of magic.

}

#' @rdname MyFun
#' @export
MyFun.algo2<-function(x, A, B, E=10, F=1000){

 #Do more magic.

}

It works but when I check the package (with check()), I keep having the same error:

checking S3 generic/method consistency ... WARNING   
MyFun:
function(x, type, A, B, ...)   
  MyFun.algo1:
function(x, A, B, C, D)

#Same thing for algo2.

See section 'Generic functions and methods' in the 'Writing R   Extensions' manual.
Found the following apparent S3 methods exported but not registered:
MyFun.algo1 MyFun.algo2   
See section 'Registering S3 methods' in the 'Writing R Extensions'   manual.

I looked into the manual but it was really not helpful. I tried changing the roxygen2 tags by adding @method and @S3method, it didn't helped. I tried changing the order of the ... and put "type" at the end in MyFun, it didn't helped neither. I don't understand... what am I doing wrong? Why am I not allowed to do this ? Is there a way around this?

Upvotes: 2

Views: 439

Answers (1)

G. Grothendieck
G. Grothendieck

Reputation: 270448

In the code in the question MyFun is not a generic and MyFun.algo1 and MyFun.algo2 are not S3 methods even though the names seem to suggest that. It would be beter to change it to something like this which is not suggestive of something it is not, won't trigger any checks and is more compact.

Myfun <- function(x, type = c("algo1", "algo2"), A, B, ...) {
  type <- match.arg(type)
  do.call(type, list(x, A, B, ...))
}

algo1 <- function(x, A, B, ...) "algo1"
algo2 <- function(x, A, B, ...) "algo2"

# test run
Myfun(1, "algo1", 2, 3)
## [1] "algo1"

# another test run
Myfun(1, A = 2, B = 3)
## [1] "algo1"

Upvotes: 2

Related Questions