从我的评论来看,有两个想法。
missing
这本质上是您的方法,稍作修改(主要是为了样式和/或可读性,只是为了美观):
foo1 <- function(x, y, z, a, b) {
# first argument set
allFirst <- ! any(missing(x), missing(y), missing(z))
anyFirst <- any(! missing(x), ! missing(y), ! missing(z))
# second argument set
allSecond <- ! any(missing(a), missing(b))
anySecond <- any(! missing(a), ! missing(b))
if ( (allFirst && anySecond) ||
(allSecond && anyFirst))
stop("provide either arguments x,y,z or a,b", call. = FALSE)
if ( (anyFirst && ! allFirst) ||
(anySecond && ! allSecond) )
stop("no complete and/or distinct argument set provided", call. = FALSE)
if (allFirst) {
return("x,y,z provided")
} else if (allSecond) {
return("a,b provided")
} else {
stop("nothing provided", call. = FALSE)
}
}
foo1(a = 1, b = 2)
# [1] "a,b provided"
foo1(x = 1, y = 2, z = 3)
# [1] "x,y,z provided"
foo1()
# Error: nothing provided
foo1(x = 1)
# Error: no complete and/or distinct argument set provided
foo1(a = 1)
# Error: no complete and/or distinct argument set provided
foo1(x = 1, b = 2)
# Error: no complete and/or distinct argument set provided
S3 方法分派
这仅在参数集由不同类区分时才有效。例如,如果x
是 adata.frame
并且a
是 a list
,那么...
请注意,第一个定义(启用其他定义)设置公共参数,因此所有函数都需要x
用作第一个参数:
foo2 <- function(x, ...) UseMethod("foo2", x)
foo2.data.frame <- function(x, y, z) {
if (missing(y) || missing(z)) stop("no complete and/or distinct argument set provided for 'x'", call. = FALSE)
return("x,y,z provided")
}
foo2.list <- function(x, b, ...) {
if (missing(b)) stop("no complete and/or distinct argument set provided for 'a'", call. = FALSE)
return("a,b provided")
}
...所以我们不能function(a, b)
在正式定义中使用。
foo2(x = data.frame(), y = 1, z = 2)
# [1] "x,y,z provided"
foo2(x = list(), b = 1)
# [1] "a,b provided"
foo2(data.frame())
# Error: no complete and/or distinct argument set provided for 'x'
foo2(x = list())
# Error: no complete and/or distinct argument set provided for 'a'
foo2()
# Error in foo2() (from #1) : argument "x" is missing, with no default
foo2(x=data.frame(), b=2)
# Error in foo2.data.frame(x = data.frame(), b = 2) (from #1) :
# unused argument (b = 2)
在第一个函数中需要使用省略号...
,但在其他两个函数中,它有点风格并且可能不是必需的,因为它允许将一些参数传递给其他伴随/依赖函数。
此处的错误消息应该更具描述性,因为(至少)所有函数都将假定第一个参数为x
(而不是a
)。
此选项正在执行一种称为多态的东西,其中函数的行为根据所提供的数据类别有很大不同。如果它总是返回相同类型的对象,这会减少一点,但即使这样,有些人还是觉得它不受欢迎。
请注意,许多标准 R 函数都使用此调度,包括c
、print
和str
。