attempt

Colin Fay

2018-01-03

{attempt} 0.1.0

A Friendlier Condition Handler for R, inspired by {purrr} mappers and based on {rlang}.

{attempt} is designed to handle the cases when something / someone attempts to do something it shouldn’t.

For example :

{attempt} provides several condition handlers, from try catch to simple message printing.

{attempt} only depends on {rlang}, making it easy to implement in other functions and packages.

Reference

attempt

attempt is a wrapper around base try that allows you to insert a custom messsage on error.

You can make it verbose (i.e. returning the expression):

Of course the result is returned if there is one:

As with try, the result cant be saved as an error object :

silent_attempt

silent_attempt is a wrapper around silently (see further down for more info) and attempt. It attempts to run the expr, stays silent if the expression succeeds, and returns error or warnings if any.

try catch

You can write a try catch with these params :

With mappers

As usual, the handlers are set only if you call them :

Traditionnal way

{attempt} is flexible in how you can specify your arguments.

You can, as you do with {base} tryCatch, use a plain old function:

You can even mix both:

try_catch_df

try_catch_df returns a tibble with the call, the error message if any, the warning message if any, and the value of the evaluated expression or “error”. The values will always be contained in a list-column.

map try_catch

map_try_catch and map_try_catch_df allow you to map on a list of arguments l, to be evaluated by the function in fun.

silently

silently transforms a function so that when you call this new function, it returns nothing unless there is an error or a warning (contrary to attempt that returns the result). In a sense, the new function stay silent unless error or warning.

With silently, the result is never returned.

surely

surely also transforms a function so that when you call this new function, it returns calls attempt() - i.e. in the code below, calling sure_log(1) is the same as calling attempt(log(1)). In a sense, you’re sure this new function will always work.

if_ conditions

if_none, if_any and if_all test the elements of the list.

The defaut for all .p is isTRUE. So you can:

if_then performs a simple “if this then do that”:

And if_else is a wrapper around base::ifelse() :

warnings and messages

The stop_if, warn_if and message_if are easy to use functions that send an error, a warning or a message if a condition is met. Each function has its counterpart with _not. That returns a message if the condition is not met.

stop_if_not is quite the same as assert_that from the {assertthat} package, except that it can takes mappers. It is not the same as base stopifnot(), as it doesn’t take a list of expression.

These functions are also flexible as you can pass base predicates (is.numeric, is.character…), a custom one built with mappers, or even your own testing function.

You can either choose a custom message or just let the built-in messages be printed:

If you have a function with no arguments, you can pass a dot . as first argument :

If you don’t specify a .p, the default test is isTRUE.

In function

That can come really handy inside a function :

none, all, any

stop_if, warn_if and message_if all have complementary tests with _all, _any and _none, which combine the if_* and the warn_*, stop_* and message_* seen before. They take a list as first argument, and a predicate. They test if any, all or none of the elements validate the predicate.

Misc

Acknowledgments

Thanks to Romain for the name suggestion.

Contact

Questions and feedbacks welcome!

You want to contribute ? Open a PR :) If you encounter a bug or want to suggest an enhancement, please open an issue.