logical(),double()等作为默认参数值的用途是什么

时间:2019-02-27 15:51:54

标签: r function arguments

在@G之后重写。格洛腾迪克的答案

Advanced R 中,关于S3 classes,我遇到了以下函数定义:

new_Date <- function(x = double()) {
  stopifnot(is.double(x))
  structure(x, class = "Date")
}

我认为将double()设置为默认值是一种强制用户为double类型输入x值的方法,但由于函数随后会使用stopifnot

阅读@G。 Grothendieck的回答,我知道double() double NA 。这是否意味着double()的使用仅允许函数使用(空)双精度模式,即使没有提供参数时(而不是抛出 missing参数错误),并且与检查x的类无关吗?

原始问题

我有时会看到将参数默认值定义为空(或定长)类型的函数,例如:

func1 <- function(a = logical(), b = numeric(1)){
    if (a){
        b
    } else {
        0
    }
}

我知道这可以简化阅读过程,以了解每个参数的类型。但这似乎并不强制参数为这种类型。

func1(a = 4, b = 3)
# 3
func1(a = 4, b = TRUE)
# TRUE

我知道,在该特定示例中,如果将if (a)更改为if (a == TRUE),如果a不符合逻辑,则会触发错误。但是通常,如果不检查函数体内的参数类型,这种参数定义的用途是什么?

我倾向于使用这种函数定义,但这要重得多:

func2 <- function(a, b){
    if (class(a) != 'logical') stop('a must be logical')
    if (!(class(b) == 'numeric' & length(b) == 1)) stop(
        'b must be numeric(1)'
    )
    ...
}

1 个答案:

答案 0 :(得分:2)

stopifnot

假设a是逻辑NA,那么它仍应返回0,然后尝试执行此操作(或如果a * b的逻辑NA应该用a替换正文的第二行)返回NA)。

无论如何,主要要点是以下stopifnot样式可用于参数检查。

func2 <- function(a, b) {
  stopifnot(is.logical(a), is.numeric(b))
  isTRUE(a) * b
}

func2(TRUE, 3)
## [1] 3

func2(9, 2)
## Error in func2(9, 2) : is.logical(a) is not TRUE

如果您要自定义错误消息,请使用stopifnot而不是if (...) stop(...),每个参数一个这样的语句。

S3和S4

请注意,可以使用S3调度到基于第一个参数的方法,也可以使用S4调度到给定的签名。如果不存在用于这种签名的方法,则会触发错误。

这是一个S4示例:

setMethod("func3", c("logical", "numeric"), function(a, b) isTRUE(a) * b)

func4(TRUE, 3)
## [1] 3

func4(2, 1)
## Error in UseMethod("func3") : 
##  no applicable method for 'func4' applied to an object of class "c('double', 'numeric')"

这是一个S3示例:

# check 1st arg using S3 dispatch and 2nd arg using stopifnot
func3 <- function(a, b) UseMethod("func4")
func3.logical <- function(a, b) {
  stopifnot(is.numeric(b))
  isTRUE(a) * b
}

func3(TRUE, 3)
## [1] 3

func3(3, 8)
## Error in UseMethod("func3") : 
##  no applicable method for 'func3' applied to an object of class "c('double', 'numeric')"

其他

CRAN上有一个名为checkmate的软件包,用于进行参数检查,其他许多软件包也使用了该软件包(替换了现已失效的ArgumentCheck软件包)。另一个用于参数类型检查的软件包是Bioconductor上的TypeInfo

有一个名为rtype的软件包,用于进行强类型检查。

还有用于类型声明的软件包assertive.typesassertiveassertrassertableassertthat

还要注意,关于问题中的代码,S3类是向量,因此可以具有多个元素,因此请使用is.someclass(如果someclass中存在这样的函数)或{{ 1}},其中inherits(X, "someclass")是感兴趣的类,而不是someclass用于检查S3类。