knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
Assertive programming follows the principles of fail fast and fail visibly. It is implemented by issuing an informative error message if the function arguments fail to satisfy specific criteria. This is particularly important in R because it is a dynamically typed language.
There are a host of R packages to facilitate assertive programming. Here I am interested in those packages that are
1) on CRAN; 2) lightweight (few or no dependencies); 3) can be used to test the types and values of common R objects (not just data frames); 4) issue error messages.
The most useful packages that I am aware of that satisfy these criteria are
This vignette consists of an overview of each package followed by a comparison.
In short the checkr
package is recommended over the alternatives if you are looking for a set of expressive, light-weight, pipe-friendly assertive functions with customizable object names.
The base
package offers the stopifnot()
function.
height <- dplyr::starwars$height stopifnot(is.character(height))
The error message is not that helpful if the user doesn't know what is.character()
tests for.
In a function it behaves as follows:
my_fun <- function(x) stopifnot(is.character(x)) my_fun(height)
The assertthat
package offers assert_that()
.
library(assertthat) assert_that(is.character(height))
The error message is a big improvement on stopifnot()
's.
In a function it behaves as follows:
my_fun <- function(x) assert_that(is.character(x)) my_fun(dplyr::starwars$height)
Perhaps the neatest feature is the ability to set your own error message for an assertion function using on_failure()
.
is.character2 <- function(x) is.character(x) on_failure(is.character2) <- function(call, env) { paste0(deparse(call$x), " must be a character - sort it out!") } assert_that(is.character2(height))
detach("package:assertthat")
The checkmate
package provides a plethora of functions to check the type and related properties of common objects.
library(checkmate) assert_character(height)
In a function it behaves as follows
my_fun <- function(x) assert_character(x) my_fun(height)
In addition, the assert()
function allows multiple alternative check**
functions (those which return a string of the error message on failure and a TRUE
on success) to be combined into one assertion.
assert(checkCharacter(height), checkFactor(height))
detach("package:checkmate")
The checkr
package provides a set of expressive functions to test the values of objects.
library(checkr) check_vector(height, "")
In a function it behaves as follows:
my_fun <- function(x) check_vector(x, "") my_fun(height)
And multiple alternative checks can be combined using the checkor()
function.
checkor(check_vector(height, ""), check_vector(height, 1))
If all checks are passed stopifnot()
returns an invisible NULL
,
while assert_that()
returns TRUE
.
In contrast, checkmate::assert_**
and checkr::check_**
return a copy of the original object which allows them to be used in pipes.
Although there is no way to customize the error message produced by stopifnot()
,
assert_that()
allows the programmer to specify the message for a individual test using the msg
argument.
In the case of checkmate
and checkr
the programmer can specify the variable name using the .var.name
and x_name
argument, respectively. This can be very helpful in functions.
my_fun <- function(x) check_vector(x, "", x_name = substitute(x)) my_fun(height)
Much of the checkmate
package is written in C
to minimize execution time.
Whereas the checkmate
package depends on backports
and utils
,
and assertthat
depends on tools
, and checkr
depends on err
only base
is dependency-free.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.