Sending the default value of an argument from a common S4 function to methods associated with it

Suppose all of your S4 methods associated with a specific common function / S4 method use a formal argument, which must have a specific default value. Intuitively, I would formulate such an argument in the definition of S4 generic (as opposed to specifying it in every definition of a method that would seem somewhat redundant to me).

However, I noticed that this way I run into problems, since it seems that the default value of the formal argument is not sent to the methods and thus an error occurs.

Is this not contrary to the idea of ​​having a combination of general and methods? Why should I again specify the formal argument in each method separately when the default value is always the same? Can I explicitly send default argument values ​​in some way?


Below you will find a brief illustration of the behavior.

General function

setGeneric( name="testFoo", signature=c("x", "y"), def=function( x, y, do.both=FALSE, ... ) { standardGeneric("testFoo") } ) 

Method

 setMethod( f="testFoo", signature=signature(x="numeric", y="numeric"), definition=function( x, y ) { if (do.both) { out <- list(x=x, y=y) } else { out <- x } return(out) } ) 

Error

 > testFoo(x=1, y=2) Error in .local(x, y, ...) : object 'do.both' not found 

The do.both fixes it

 setMethod( f="testFoo", signature=signature(x="numeric", y="numeric"), definition=function( x, y, do.both=FALSE ) { if (do.both) { out <- list(x=x, y=y) } else { out <- x } return(out) } ) > testFoo(x=1, y=2) [1] 1 
+6
source share
1 answer

When you call testFoo(x=1, y=2) , S4 generic is first processed, which searches for the method, finds it and sends it a call that looks like this: testFoo(x=1, y=2, do.both=FALSE, ...) .

In the words ?standardGeneric :

'standardGeneric dispatches a method defined for a generic function named "f" using the actual arguments in the frame from which it is called.

If the method by which it sends this call does not accept the do.both argument, the method --- like any other R function , throws an error. No function can handle a call containing the argument foo if this function definition does not contain (a) the formal argument foo or (b) the argument "dots", ... that can absorb arbitrary arguments.

Basically, what you tried is no different from the following, which fails in a similar way, but is perhaps easier to understand:

 testFooGeneric <- function(x=1, y=2, do.both=FALSE, ...) { ## The line below does essentially what standardGeneric() does if(is.numeric(x) & is.numeric(y)) { testFooMethod(x=x, y=y, do.both=do.both) } } testFooMethod <- function(x, y) { cat("Success!\n") } testFooGeneric(x=1, y=2) # Error in testFooMethod(x = x, y = y, do.both = do.both) : # unused argument(s) (do.both = do.both) 

To fix this, you need to override testFooMethod() one of the following two ways: either of them will also fix your S4 method:

 ## Option 1 testFooMethod <- function(x, y, do.both) { cat("Success!\n") } testFooGeneric(x=1, y=2) # Success! ## Option 2 testFooMethod <- function(x, y, ...) { cat("Success!\n") } testFooGeneric(x=1, y=2) ## Success! 
+7
source

Source: https://habr.com/ru/post/925721/


All Articles