0

假设我们希望我们的函数能够处理两种情况:

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意识到这两种情况之间的区别?

4

2 回答 2

3

如果你可以保证它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
于 2013-10-12T16:13:04.097 回答
1

我不知道自动执行此操作的方法,但是在处理这些类型的情况时,有时使用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类型语句)。归根结底,这还取决于您是否可以预测一组合理的默认值。

如果您的函数很复杂,您可能希望将进入switches 的步骤分离到单独的函数中,因为这可能会导致代码更具可读性(并且更易于重用)。

于 2013-10-13T10:54:30.950 回答