S4 отсутствует или нулевые аргументы в пользу методов?
Вопрос
Есть ли способ определить, что происходит, когда аргумент метода отсутствует или нулевой?
В приведенном ниже примере я хотел бы вызвать ту же функцию независимо от того, печатаю ли я foo()
или же foo(NULL)
. Анкет Конечно, я знаю, что у меня есть метод setMethod("foo","NULL",function(x) foo())
Но это репликация кода и возможный источник ошибок.
Спасибо!
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"
Решение
Почти ровно на три года опоздание на вечеринку, но вы действительно хотите 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
Создает виртуальный класс, который является суперклассом (родителем) для классов компонентов, поэтому оба ребенка наследуют от этого класса, что означает, что вы можете отправить одну и ту же функцию против каждого ребенка.
Другие советы
С использованием setMethod("foo","NULL",function(x) foo())
не является репликацией кода, поскольку вы не реплицируете код, но вы звоните. Я бы сказал, что это очень хороший способ решения вашей проблемы.
Я предполагаю, что соответствующий способ - использовать «любой» в подписи:
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"
Убедитесь, что вы указываете любую другую возможность, о которой вы хотите позаботиться, как «любое» также берет все остальные, которые не соответствуют подписи другого метода.
Если у вас есть аргументы, которые могут отсутствовать, вы можете просто не указать их в подписи SetMethods и установить по умолчанию в общем. Это - в моем скромном виде - лучший выбор дизайна.
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
Теперь вы можете справиться с Null Code в коде, как вы бы сделали с отсутствующими аргументами.
На Sidenote: теперь я добавил NULL в качестве значения по умолчанию, но во многих случаях существует гораздо более разумный выбор для значений по умолчанию. Просто помните, что SetMethod берет начальную подпись, и что когда Y установлен как нулевая, это не заменяется по умолчанию.
например:
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)
Грязный взлом:
Я нахожу этот подход немного неловким, но вот грязный хак, который устанавливает все отсутствующие параметры на 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")
}
Попробуй это, вы получаете:
> foo(1)
[1] "numeric"
> foo(NULL)
[1] "NULL"
> foo()
[1] "NULL"
Таким образом, вы больше никогда не отправляете пропавшего без вести. Вы можете просто забыть об этом. Но это не подходящий способ сделать это ...