Introduction

set.seed(19790801) library(assertive) knitr::opts_chunk$set(error = FALSE)

assert functions

There are times when it is a good idea to check the state of your variables, to ensure that they have the properties that you think they have. For example, if you have a count variable, you might want to check that it is numeric, that all the values are non-negative, and that all the values are whole numbers.

Base-R has a function called stopifnot that lets you perform such checks.

counts <- c(1, 2, 3, 4.5) stopifnot( is.numeric(counts), all(counts >= 0), isTRUE(all.equal(counts, round(counts))) )

This is OK, but not that easy to read. Worse, the error messages that it produces in the event of failure aren't very user-friendly.

assertive provides lots of assert functions that provide checks for specific conditions. (An assertion is software development jargon for a check.) They are designed to make your code easier to read, and to return helpful error messages to users in the event of a check failing.

Here's the same example again, written in an assertive style.

counts <- c(1, 2, 3, 4.5) assert_is_numeric(counts) assert_all_are_non_negative(counts) assert_all_are_whole_numbers(counts)

Here you see that the error message contains a human readable sentence, followed by information on the values that caused problems, along with their positions and reasons for failure.

is and has functions

Each of the assert functions has an underlying is or has function. For example, assert_is_numeric calls is_numeric, assert_all_are_non_negative calls is_non_negative, and so on.

Some is and has functions, such as is_numeric, return a single logical value.

is_numeric(1:6) is_numeric(letters)

When the check passed, is_numeric returned TRUE, and when it failed, is_numeric returned FALSE with a cause attribute explaining the problem.

Where is functions return a single value, they have a single corresponding assert function prefixed by assert_. For example, is_numeric is paired with assert_is_numeric.

Some is and has functions, such as is_non_negative, return a logical vector.

is_non_negative(rnorm(6))

is_non_negative returned a logical vector which was TRUE where the check passed, and FALSE where the check failed. This time the cause attribute was also vectorised, returning an empty string for the passes and a brief explanation of the problem for the failures.

Where is functions return a vector, there are two corresponding assert functions, prefixed assert_all_are_, and assert_any_are_. For example, is_non_negative is paired with assert_all_are_non_negative and assert_any_are_non_negative.

Summary

  1. assertive contains is* functions that return logical values or vectors, with a cause attribute the describes what went wrong when the return value is not \code{TRUE}.
  2. assertive also contains assert* functions that throw an error if a conditon is not met (and do nothing if the condition is met).
  3. If a function is_something returns a single value, then the corresponding assert* function is named assert_is_something.
  4. If a function is_something returns a vector, then the corresponding assert* functions are named assert_all_are_something and assert_any_are_something.

Exercises.

  1. List the contents of the assertive package using ls("package:assertive"). [1 min].
  2. Find a function that will throw an error if its input is not a vector. Run the examples for that function Hint: The pattern argument to ls may be useful for narrowing your search. [2 mins].
  3. Find a function that will throw an error if its input contains values that aren't whole numbers. Run the example. [2 mins].
  4. Find a function that returns a logical vector if its input contains US zip codes. Run the example. [2 mins].