在给定 S4 方法中将参数值显式分派给后续 S4 方法时,如何避免经典Error: argument "<argname>" is missing, with no default
错误(参见下面的示例) 。
例子
大图
- 有一个
foo()
调用 method的方法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()