特定の S4 メソッドの後続の S4 メソッドに引数値を明示的にError: argument "<argname>" is missing, with no default
ディスパッチするときの古典的なエラー (以下の例を参照)を回避するにはどうすればよいですか。
例
大局
- method
foo()
を呼び出すメソッドがありbar()
ます。 x
どちらのメソッドも、引数およびに依存しますy
。- メソッドは、引数およびを明示的な方法で
foo()
ディスパッチします: .x
y
bar()
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()