当前位置: 首页 > 知识库问答 >
问题:

在R函数中指定可选参数的“正确”方法

唐恺
2023-03-14

我对在r中用可选参数编写函数的“正确”方式感兴趣。随着时间的推移,我偶然发现了几段在这里采取不同路线的代码,并且我无法在这个主题上找到一个合适的(官方)位置。

到目前为止,我已经写了这样的可选参数:

fooBar <- function(x,y=NULL){
  if(!is.null(y)) x <- x+y
  return(x)
}
fooBar(3) # 3
fooBar(3,1.5) # 4.5

如果仅提供 x,则该函数仅返回其参数。它对第二个参数使用默认的 NULL 值,如果该参数恰好不是 NULL,则该函数将两个数字相加。

或者,可以像这样编写函数(其中第二个参数需要按名称指定,但也可以取消list(z)或定义z

fooBar <- function(x,...){
  z <- list(...)
  if(!is.null(z$y)) x <- x+z$y
  return(x)
}
fooBar(3) # 3
fooBar(3,y=1.5) # 4.5

就我个人而言,我更喜欢第一个版本。然而,我可以看到两者的优缺点。第一个版本不太容易出错,但是第二个版本可以用来包含任意数量的选项。

有没有一种“正确”的方法来指定R中的可选参数?到目前为止,我已经确定了第一种方法,但两者偶尔都会感觉有点“hacky”。


共有3个答案

秦光启
2023-03-14

以下是我的经验法则:

如果可以从其他参数计算默认值,请使用默认表达式,如下所示:

fun <- function(x,levels=levels(x)){
    blah blah blah
}

否则使用missing

fun <- function(x,levels){
    if(missing(levels)){
        [calculate levels here]
    }
    blah blah blah
}

在极少数情况下,您可能希望用户指定一个持续整个 R 会话的默认值,请使用 getOption

fun <- function(x,y=getOption('fun.y','initialDefault')){# or getOption('pkg.fun.y',defaultValue)
    blah blah blah
}

如果某些参数根据第一个参数的类适用,请使用 S3 泛型:

fun <- function(...)
    UseMethod(...)


fun.character <- function(x,y,z){# y and z only apply when x is character
   blah blah blah 
}

fun.numeric <- function(x,a,b){# a and b only apply when x is numeric
   blah blah blah 
}

fun.default <- function(x,m,n){# otherwise arguments m and n apply
   blah blah blah 
}

使用<代码>...仅当您将附加参数传递给另一个函数时

cat0 <- function(...)
    cat(...,sep = '')

最后,如果您选择使用< code >...在不将点传递给另一个函数的情况下,警告用户您的函数将忽略任何未使用的参数,否则会非常混乱:

fun <- (x,...){
    params <- list(...)
    optionalParamNames <- letters
    unusedParams <- setdiff(names(params),optionalParamNames)
    if(length(unusedParams))
        stop('unused parameters',paste(unusedParams,collapse = ', '))
   blah blah blah 
}
商柏
2023-03-14
匿名用户

老实说,我喜欢OP的第一种方式,它实际上以< code>NULL值开始,然后用< code>is.null检查它(主要是因为它非常简单和容易理解)。这可能取决于人们习惯的编码方式,但是Hadley似乎也支持< code>is.null方式:

摘自Hadley的书“Advanced-R”第6章,Functions,p.84(在线版本请在此处查看):

您可以确定是否使用 missing() 函数提供了参数。

i <- function(a, b) {
  c(missing(a), missing(b))
}
i()
#> [1] TRUE TRUE
i(a = 1)
#> [1] FALSE  TRUE
i(b = 2)
#> [1]  TRUE FALSE
i(1, 2)
#> [1] FALSE FALSE

有时您想要添加一个重要的默认值,这可能需要几行代码来计算。如果需要,您可以使用missing()有条件地计算它,而不是在函数定义中插入代码。但是,如果不仔细阅读文档,就很难知道哪些参数是必需的,哪些是可选的。相反,我通常将默认值设置为NULL,并使用is.null()来检查是否提供了参数。

卫琛
2023-03-14

您还可以使用 missing() 来测试是否提供了参数 y

fooBar <- function(x,y){
    if(missing(y)) {
        x
    } else {
        x + y
    }
}

fooBar(3,1.5)
# [1] 4.5
fooBar(3)
# [1] 3
 类似资料:
  • 问题内容: 最近,我与队友讨论了 在方法中使用可选参数的问题。 假设方法是 接受一个和 可选参数 ,它返回该目录中列出的书籍,如果还传递了类别,则仅返回该类别中的书籍。 冲突点是,验证是否为空检查。我认为不应对此进行空检查,因为它是可选参数。函数的调用者可以通过或,并且函数应在实现中处理两种情况。 我的意见是,对于可选参数,只会使方法的约定更加明确。只需查看方法签名即可知道此参数是可选的,不需要读

  • 最近,我和我的队友讨论了在方法中使用作为可选参数。 假设方法是 我的观点是,对于可选参数,只会使方法的契约更加清晰。只要看一下方法签名就可以知道这个参数是可选的,不需要读取JavaDocs。但当他不想使用该可选参数时,不应强制他传递。 我的队友有不同的看法。他希望对其进行空检查,从而强制调用方始终传递。他的观点是为什么我们要通过一个空的可选选项。此外,看起来比更易读。 这个方法在我们的一个库包中,

  • 我有以下练习: 添加代码以使其正常运行。 我加了一个私人财产 和一个公共构造师 我添加了int-val,作为构造函数为MyVal分配一个非临时对象地址的一种方式,比如x。 有没有一个简洁(呃)的方法来回答这个练习?

  • 问题内容: 您能否指出我跳过JavaScript中可选参数的好方法。 例如,我想在这里丢弃所有参数: 问题答案: 解: 您应该使用而不是要跳过的可选参数,因为这100%会模拟JavaScript中可选参数的默认值。 小例子: 强烈建议 :如果您有很多参数,请使用JSON,并且可以在参数列表的中间包含可选参数。看看这是如何在jQuery中完成的。

  • 当我将firstThing(第一件事)设置为default(默认值)时,如果没有默认值nil(默认值),这将起作用,我会得到一个错误,即调用函数时缺少参数。 通过键入Int 我认为它使它成为可选的,默认值为零,对吗?如果是这样,为什么没有=nil它就不能工作?

  • 问题内容: 假设我有一个PHP函数foo: 有什么办法只能指定第二个可选参数? 例: 问题答案: PHP本身不支持命名参数作为函数。但是,有一些方法可以解决此问题: 使用数组作为该函数的唯一参数。然后,您可以从数组中提取值。这允许在数组中使用命名参数。 如果要根据上下文允许可选数量的参数,则可以使用func_num_args和func_get_args而不是在函数定义中指定有效参数。然后,根据参数