Is there a way to define what happens when the argument of a method is missing or NULL?
In the example below, I'd like to call the same function no matter whether I type foo()
or foo(NULL)
. Of course I know that I can have a method setMethod("foo","NULL",function(x) foo())
but that that's code replication and a possible source of mistakes.
Thanks!
setGeneric("foo",function(x) standardGeneric("foo"))
setMethod("foo","numeric",function(x) "numeric")
setMethod("foo","NULL",function(x) "NULL")
setMethod("foo","missing",function(x) "missing")
R> foo(1)
[1] "numeric"
R> foo()
[1] "missing"
R> foo(NULL)
[1] "NULL"
Almost exactly three years late to the party, but you really want setClassUnion
:
> setClassUnion("missingOrNULL", c("missing", "NULL"))
> setGeneric("foo",function(x) standardGeneric("foo"))
> setMethod("foo","numeric",function(x) "numeric")
> setMethod("foo","missingOrNULL",function(x) "NULL")
> foo(1)
[1] "numeric"
> foo()
[1] "NULL"
> foo(NULL)
[1] "NULL"
setClassUnion
creates a virtual class that is a superclass (parent) to the component classes, so then both children inherit from that class, which means you can dispatch the same function against each child.
Using setMethod("foo","NULL",function(x) foo())
is not a code replication, since you don't replicate code but put a call to it. I would say it is a very good way of solving your problem.
I guess the appropriate way is to use "ANY" in the signature:
setGeneric("foo",function(x) standardGeneric("foo"))
setMethod("foo","numeric",function(x) "numeric")
setMethod("foo","ANY",function(x) "ANY")
> foo(1)
[1] "numeric"
> foo()
[1] "ANY"
> foo(NULL)
[1] "ANY"
Make sure you specify every other possibility that you want taken care of, as "ANY" also takes all the rest that doesn't fit to the signature of another method.
If you have arguments that can be missing, you can just not specify them in the signature of setMethods and set a default in the generic. This is -in my humble view- a better design choice.
setGeneric("foo",function(x,y=NULL,...) {
standardGeneric("foo")
})
setMethod("foo",c("numeric","ANY"),function(x,y,...) {
print(y)
})
setMethod("foo",c("numeric","numeric"),function(x,y,...) {
x + y
})
> foo(1)
NULL
> foo(1,3)
[1] 4
> foo(1,NULL)
NULL
Now you can deal with the NULL cases in-code like you would do with the missing arguments.
On a sidenote: Now I added NULL as default value, but in many cases there are far more sensible choices for default values. Just remember that the setMethod takes the initial signature, and that when y is set as NULL, this is not replaced by the default.
eg:
setGeneric("bar",function(x,y=2,...) {
standardGeneric("bar")
})
setMethod("bar",c("numeric","ANY"),function(x,y,...) {
x + y
})
setMethod("bar",c("numeric","numeric"),function(x,y,...) {
x - y
})
> bar(1)
[1] 3
> bar(1,2)
[1] -1
> bar(1,NULL) # this y is not replaced with the default!
numeric(0)
DIRTY HACK :
I find the approach a bit awkward, but here is a dirty hack that sets all missing parameters to NULL :
setGeneric("foo",function(x,y,z) {
pars <- names(formals(foo))
for(i in pars){
tryerr <- try(get(i),silent=T)
if(is(tryerr,"try-error")){ assign(i,NULL)}
}
standardGeneric("foo")
}
Trying this, you get :
> foo(1)
[1] "numeric"
> foo(NULL)
[1] "NULL"
> foo()
[1] "NULL"
So you never dispatch to the missing any more. You can just forget about it. But this ain't the appropriate way of doing things...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With