S4 отсутствует или нулевые аргументы в пользу методов?

StackOverflow https://stackoverflow.com/questions/4440363

  •  09-10-2019
  •  | 
  •  

Вопрос

Есть ли способ определить, что происходит, когда аргумент метода отсутствует или нулевой?

В приведенном ниже примере я хотел бы вызвать ту же функцию независимо от того, печатаю ли я 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"

Таким образом, вы больше никогда не отправляете пропавшего без вести. Вы можете просто забыть об этом. Но это не подходящий способ сделать это ...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top