假设我们希望我们的函数能够处理两种情况:
somefun = function(x, y, method, ...) {
res = dowith(x, y)
res
}
somefun = function(z, method, ...) {
x = z$v1
y = z$v2
res = dowith(x, y)
res
}
我们如何才能somefun
意识到这两种情况之间的区别?
假设我们希望我们的函数能够处理两种情况:
somefun = function(x, y, method, ...) {
res = dowith(x, y)
res
}
somefun = function(z, method, ...) {
x = z$v1
y = z$v2
res = dowith(x, y)
res
}
我们如何才能somefun
意识到这两种情况之间的区别?
如果你可以保证它x
永远不会是一个列表,你可以用is.list(x)
它来确定正在调用哪个版本的函数。否则,您可以使用missing
:
somefun<-function(x,y,method,...){
if(missing(y)){
cat("Using List version\n")
y<-x$y
x<-x$x
}
else{
cat("Using normal version\n")
}
c(x,y)
}
> somefun(list(x=1,y=2),method="a method")
Using List version
[1] 1 2
> somefun(1,2,method="a method")
Using normal version
[1] 1 2
>
但是,请注意,如果您这样做,并且您想使用该函数的列表版本,那么method
它之后的所有内容都必须按名称传递,否则 R 会将它们绑定到y
:
> somefun(list(x=1,y=2),"a method")
Using normal version
$x
[1] 1
$y
[1] 2
[[3]]
[1] "a method"
> somefun(list(x=1,y=2),method="a method",5)
Using normal version
$x
[1] 1
$y
[1] 2
[[3]]
[1] 5
> somefun(list(x=1,y=2),method="a method",q=5)
Using List version
[1] 1 2
我不知道自动执行此操作的方法,但是在处理这些类型的情况时,有时使用switch
. 这是一个基本示例:
somefun <- function(x, y = NULL, type = c("DF", "vecs"), method = NULL, ...) {
switch(type,
DF = sum(x[["v1"]], x[["v2"]]),
vecs = sum(x, y),
stop("'type' must be either 'DF' or 'vecs'"))
}
somefun(x = 10, y = 3, type="vecs")
# [1] 13
somefun(x = data.frame(v1 = 2, v2 = 4), type="DF")
# [1] 6
somefun(x = data.frame(v1 = 2, v2 = 4), type = "meh")
# Error in somefun(x = data.frame(v1 = 2, v2 = 4), type = "meh") :
# 'type' must be either 'DF' or 'vecs'
在上面,我们期望用户必须输入一个type
参数,其中可接受的值为“DF”或“vecs”,并且为每个选项定义了一组不同的操作。
当然,我还会编写一组不同的场景脚本,并在函数开始时使用一些条件检查来确保事情会按预期工作。例如,如果您希望大多数时候人们会输入 a data.frame
,您可以执行类似的操作if (is.null(y) & is.null(type)) temp <- "DF"
(或在其中插入try
类型语句)。归根结底,这还取决于您是否可以预测一组合理的默认值。
如果您的函数很复杂,您可能希望将进入switch
es 的步骤分离到单独的函数中,因为这可能会导致代码更具可读性(并且更易于重用)。