Be assertive!
assertive, my new package for writing robust code, is now on CRAN. It consists of lots of is
functions for checking variables, and corresponding assert
functions that throw an error if the condition doesn’t hold. For example, is_a_number
checks that the input is numeric and scalar.
is_a_number(1) #TRUE is_a_number("a") #FALSE is_a_number(1:10) #FALSE
In the last two cases, the return value of FALSE has an attribute “cause
” that indicates the cause of failure. When “a” is the input, the cause is “"a" is not of type 'numeric'.
“, whereas for 1:10
, the cause is “1:10 does not have length one.
“. You can get or set the cause attribute with the cause
function.
m <- lm(uptake ~ 1, CO2) ok <- is_empty_model(m) if(!ok) cause(ok)
The assert
functions call an is
function, and if the result is FALSE, they throw an error; otherwise they do nothing.
assert_is_a_number(1) #OK assert_is_a_number("a") #Throws an error
There are also some has
functions, primarily for checking the presence of attributes.
has_names(c(foo = 1, bar = 4, baz = 9)) has_dims(matrix(1:12, nrow = 3))
Some functions apply to properties of vectors. In this case, the assert
functions can check that all the values conform to the condition, or any of the values conform.
x <- -2:2 is_positive(x) #The last two are TRUE assert_any_are_positive(x) #OK assert_all_are_positive(x) #Error
“Why would you want to use these functions?”, you may be asking. The dynamic typing and extreme flexibility of R means that it is very easy to have variables that are the wrong format. This is particularly true when you are dealing with user input. So while you know that the sales totals passed to your function should be a vector of non-negative numbers, or that the regular expression should be a single string rather than a character vector, your user may not. You need to check for these invalid conditions, and return an error message that the user can understand. assertive makes it easy to do all this.
Since this is the first public release of assertive, it hasn’t been widely tested. I’ve written a moderately comprehensive unit-test suite, but there are likely to be a few minor bugs here and there. In particular, I suspect there may be one or two typos in the documentation. Please give the package a try, and let me know if you find any errors, or if you want any other functions adding.
I like it! It’s so readable.
http://code.google.com/p/hamcrest/
Interesting library. The syntax looks remarkably like R’s testthat package, so I wonder if it is a descendant of hamcrest.
Ah, that’s why I thought that I have seen a similar R package đŸ™‚ I just wonder why you wouldn’t reuse or extend thestthat? I would guess that the assert_all_are_positive(x) example would become “assert_that(all(are_positive()), x)”. Not quite that readable than your syntax, but more flexible: the any eample just needs on moew method: “assert_that(any(are_positive()), x)”.
testthat has a slightly different purpose: it’s designed for unit testing. So testthat code belongs in the inst/tests folder of your package, whereas as assertive code is designed to be contained inside your R functions (in the R folder). And the main benefit of providing functions that test for specific things is that you can provide more readable error messages. I will have a think about how to make things more general though.
I think there’s some connection, though, in that the conditions you want to check in tests and assertions are similar. I’ve also wondered about some more declarative way to describe assertions, e.g. assert(is.numeric(x) && length(x) == 2), that could still produce nice error messages.
A way of passing in arbitrary conditions to be checked does seem useful. I’ve half an idea of how to implement it, so cross your fingers for the next release.
looks really good; I’m downloading it now. It seems like it could be really useful for error-proofing code
While I’m not yet by any stretch writing code for the masses. I am a huge superfan of useful error messages! Thanks!
Ah, lovely error messages. Do you have a github repo anywhere perchange?
The development version is hosted on Bitbucket.
https://bitbucket.org/richierocks/assertive
Is it open for forking, etc.? I can an authorisation error when I follow your link.
Bitbucket doesn’t currently support anonymous access to repositories afaik, so you’ll have to sign up for an account. (Free accounts are available.) Once you log in, you should be able to clone it.
I’m happy to accept contributions if you have ideas for new functions.
Sorry to turn this thread into a bit-bucket trail, but sadly even when I am logged in with a (free) account I can’t see your repo (or any of your repos): http://imgur.com/a/XNJX8 .
Hmm, seems I’d somehow accidentally marked the repo as private. Try again now; it should work this time.