7

メソッドの引数が見つからないか NULLの場合にどうなるかを定義する方法はありますか?

以下の例では、 と のどちらを入力しても同じ関数を呼び出したいと思い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"
4

3 に答える 3

13

パーティーにほぼ正確に 3 年遅れていますが、本当に欲しいのは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コンポーネント クラスのスーパークラス (親) である仮想クラスを作成するため、両方の子がそのクラスから継承されます。つまり、各子に対して同じ関数をディスパッチできます。

于 2013-12-13T23:27:27.950 に答える
3

コードを複製するのではなく、コードを呼び出すため、使用setMethod("foo","NULL",function(x) foo())はコードの複製ではありません。それはあなたの問題を解決するための非常に良い方法だと思います.

于 2010-12-14T15:11:27.027 に答える
2

適切な方法は、署名で「ANY」を使用することだと思います。

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"

「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 のケースを処理できます。

余談ですが、デフォルト値として NULL を追加しましたが、多くの場合、デフォルト値にははるかに賢明な選択肢があります。setMethod が最初の署名を取得すること、および y が NULL として設定されている場合、これはデフォルトで置き換えられないことを覚えておいてください。

例えば:

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"

したがって、行方不明者に派遣することはもうありません。あなたはそれを忘れることができます。しかし、これは物事を行う適切な方法ではありません...

于 2010-12-15T12:39:25.987 に答える