简体   繁体   中英

What is the use of logical(), double(), etc. as default argument value

Rewritten after @G. Grothendieck's answer

In Advanced R , about S3 classes , I came across the following function definition :

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

I thought giving double() as default value was a way of coercing the user to enter a double value for x type, but it appears it is not since the function checks afterwards with stopifnot .

Reading @G. Grothendieck's answer, I understand that double() is a double NA . Does this mean that the usage of double() is only to allow the function to work with an (empty) double even when no argument is provided (rather than throwing the missing argument error), and has nothing to do with checking on x's class ?

Original question

I sometimes see functions defined with default values for arguments as an empty (or fixed-length) type, as such :

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

I understand that it simplifies reading to know what type of each argument is. But it does not appear to force the argument to be this type.

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

I know that if, in that specific example, I change if (a) into if (a == TRUE) , it will trigger an error if a is not a logical. But in general, if there is no checking on arguments' type inside the function's body, what is the use of this type of argument definition ?

I would tend to prefer that kind of function definition, but it is far heavier :

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)'
    )
    ...
}

stopifnot

Assuming that if a is a logical NA then it should still return 0 then try this (or replace the second line of the body with a * b if a logical NA for a should return NA).

At any rate the main point is that the following stopifnot style can be used for argument checking.

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

Instead of stopifnot use if (...) stop(...) , one such statement per argument, if you want custom error messages.

S3 and S4

Note that it is possible to use S3 to dispatch to a method based on the first argument or S4 to dispatch to a given signature. If a method for such a signature does not exist an error will be triggered.

Here is an S4 example:

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')"

Here is an S3 example:

# 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')"

Other

There is a package on CRAN called checkmate for argument checking that is used by quite a few other packages (replacing the now defunct ArgumentCheck package). Another package for type checking of arguments is TypeInfo on Bioconductor.

There is a package called rtype for strong type checking.

Also there are packages assertive.types , assertive , assertr , assertable and assertthat for type assertions.

Also note that regarding the code in the question that an S3 class is a vector and so can have more than one element so use is.someclass (if such a function exists for someclass ) or inherits(X, "someclass") where someclass is the class of interest rather than class(X) == "someclass" for checking S3 classes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM