4

特定の S4 メソッドの後続の S4 メソッドに引数値を明示的にError: argument "<argname>" is missing, with no defaultディスパッチするときの古典的なエラー (以下の例を参照)を回避するにはどうすればよいですか。


大局

  • methodfoo()を呼び出すメソッドがありbar()ます。
  • xどちらのメソッドも、引数およびに依存しますy
  • メソッドは、引数およびを明示的な方法でfoo()ディスパッチします: .xybar()bar(x=x, y=y)

foo()ここで重要な点は、渡された引数の一部またはすべてbar()が欠落していても気にしたくないということです。

ジェネリック メソッド

setGeneric(
    name="foo",
    signature=c("x", "y"),
    def=function(x, y, ...) {
        standardGeneric("foo")
    }
)
setGeneric(
    name="bar",
    signature=c("x", "y"),
    def=function(x, y, ...) {
        standardGeneric("bar")
    }
)

メソッドbar()

setMethod(
    f="bar", 
    signature=signature(x="missing", y="missing"), 
    definition=function(x, y, ...) {
        print("Doing what I'm supposed to do when both args are missing")
        return(NULL)
    }
)
setMethod(
    f="bar", 
    signature=signature(x="ANY", y="missing"), 
    definition=function(x, y, ...) {
        message("'y' is missing, but I can give you 'x':")
        print(x)
        return(NULL)
    }
)
setMethod(
    f="bar", 
    signature=signature(x="missing", y="ANY"), 
    definition=function(x, y, ...) {
        message("'x' is missing, but I can give you 'y':")
        print(y)
        return(NULL)
    }
)
setMethod(
    f="bar", 
    signature=signature(x="ANY", y="ANY"), 
    definition=function(x, y, ...) {
        message("x:")
        print(x)
        message("y:")
        print(y)
        return(NULL)
    }
)

方法foo()

前述のように、foo()渡された引数の一部またはすべてbar()が欠落していても気にしたくありません。bar()明示的な方法ですべてを渡すことになっています:

setMethod(
    f="foo", 
    signature=signature(x="ANY", y="ANY"), 
    definition=function(x, y, ...) {
        bar(x=x, y=y)    
    }
)

メソッド def は一見良さそうに見えますが、呼び出し時にxまたはyが欠落していると失敗します。

> foo(x="Hello", y="World!")
x:
[1] "Hello"
y:
[1] "World!"
NULL
> foo(x="Hello")
Error in bar(x = x, y = y) : 
  error in evaluating the argument 'y' in selecting a method for function 'bar': Error: argument "y" is missing, with no default
> foo()
Error in bar(x = x, y = y) : 
  error in evaluating the argument 'x' in selecting a method for function 'bar': Error: argument "x" is missing, with no default

回避策

これは、これまでに思いついた唯一の回避策です。

setMethod(
    f="foo", 
    signature=signature(x="ANY", y="ANY"), 
    definition=function(x, y, ...) {
        if (missing(x) && missing(y)) {
            bar()    
        } else if (missing(x)) {
            bar(y=y)
        } else if (missing(y)) {
            bar(x=x)
        } else {
            bar(x=x, y=y)
        }
    }
)

> foo(x="Hello", y="World!")
x:
[1] "Hello"
y:
[1] "World!"
NULL
> foo(x="Hello")
'y' is missing, but I can give you 'x':
[1] "Hello"
NULL
> foo(y="World!")
'x' is missing, but I can give you 'y':
[1] "World!"
NULL
> foo()
[1] "Doing what I'm supposed to do when both args are missing"
NULL

if ... elseそれは機能しますが、すべてのステートメントのために、私はそれがあまり好きではありません. 「if-else ロジック」全体は、 のさまざまなメソッドの仕様に既に含まれていbar()ます。結局のところ、メソッド ディスパッチャを最初に用意することの要点はそこにあるのではないでしょうか。したがって、私はステートメントを「望ましくない作業」と見なし、より良い方法を探しています。

もちろん、すべての「重要な」引数のデフォルト値として使用することに頼ることもできますが、できるだけ関数内ではなくにNULL依存したいと思います。missing()is.null()

4

1 に答える 1

4

ここに別のアイデアがあります。(これは、R のモデル適合関数の多くで使用される一種の「言語でのコンピューティング」に広く影響を受けています。)

setMethod(
    f="foo", 
    signature=signature(x="ANY", y="ANY"), 
    definition=function(x, y, ...) {
        mc <- match.call()
        mc[[1]] <- quote(bar)
        eval(mc)
    }
)


foo(x="Hello")
# 'y' is missing, but I can give you 'x':
# [1] "Hello"
# NULL

foo(y="World")
# 'x' is missing, but I can give you 'y':
# [1] "World"
# NULL

foo()
# [1] "Doing what I'm supposed to do when both args are missing"
# NULL
于 2014-03-11T16:16:26.057 に答える