Title: | Tools for Defensive Programming |
---|---|
Description: | Tools for defensive programming, inspired by 'purrr' mappers and based on 'rlang'.'attempt' extends and facilitates defensive programming by providing a consistent grammar, and provides a set of easy to use functions for common tests and conditions. 'attempt' only depends on 'rlang', and focuses on speed, so it can be easily integrated in other functions and used in data analysis. |
Authors: | Colin Fay [aut, cre] |
Maintainer: | Colin Fay <[email protected]> |
License: | MIT + file LICENSE |
Version: | 0.3.0 |
Built: | 2024-12-21 04:25:16 UTC |
Source: | https://github.com/colinfay/attempt |
Tools for defensive programming in R.
'attempt' extends and facilitates defensive programming by providing a consistent grammar, and
provides a set of easy to use functions for common tests and conditions. 'attempt' only depends
on rlang
& withr
, and focuses on speed, so it can be easily integrated in other functions and used
in data analysis.
colin <[email protected]>
A wrapper around base try that allows you to set a custom message when an error/warning occurs.
attempt
returns the value if there are no errors or messages.
attempt(expr, msg = NULL, verbose = FALSE, silent = FALSE)
attempt(expr, msg = NULL, verbose = FALSE, silent = FALSE)
expr |
the expression to be evaluated |
msg |
the message to return if an error or warning occurs |
verbose |
whether to return the expression producing the error |
silent |
whether the error should be silent |
## Not run: attempt(log("a"), msg = "Nop !") ## End(Not run)
## Not run: attempt(log("a"), msg = "Nop !") ## End(Not run)
Prevent a funtion from printing message or warning
discretly(.f)
discretly(.f)
.f |
the function to wrap |
an error if any, a warning if any, the result if any
## Not run: discrete_mat <- discretly(matrix) discrete_mat(1:3, 2) ## End(Not run)
## Not run: discrete_mat <- discretly(matrix) discrete_mat(1:3, 2) ## End(Not run)
Test for all, any or none
if_all(.l, .p = isTRUE, .f) if_any(.l, .p = isTRUE, .f) if_none(.l, .p = isTRUE, .f)
if_all(.l, .p = isTRUE, .f) if_any(.l, .p = isTRUE, .f) if_none(.l, .p = isTRUE, .f)
.l |
the list to test. |
.p |
the predicate for testing. Defaut is |
.f |
a mapper or a function run if .p(.x) is TRUE. |
If .p(.x) is TRUE, .f() is run.
if_all(1:10, ~ .x < 11, ~ return(letters[1:10])) if_any(1:10, is.numeric, ~ return(letters[1:10])) if_none(1:10, is.numeric, ~ return(letters[1:10]))
if_all(1:10, ~ .x < 11, ~ return(letters[1:10])) if_any(1:10, is.numeric, ~ return(letters[1:10])) if_none(1:10, is.numeric, ~ return(letters[1:10]))
If this, then that
if_then(.x, .p = isTRUE, .f) if_not(.x, .p = isTRUE, .f) if_else(.x, .p = isTRUE, .f, .else)
if_then(.x, .p = isTRUE, .f) if_not(.x, .p = isTRUE, .f) if_else(.x, .p = isTRUE, .f, .else)
.x |
the object to test. If |
.p |
the predicate for testing. Defaut is |
.f |
a mapper or a function run if .p(.x) is TRUE |
.else |
a mapper or a function run if .p(.x) is not TRUE |
Depending on wether or not .p(.x) is TRUE, .f() or .else() is run.
If you want these function to return a value,
you need to wrap these values into a mapper / a function. E.g, to return
a vector, you'll need to write if_then(1, is.numeric, ~ "Yay")
.
a <- if_then(1, is.numeric, ~"Yay") a <- if_not(1, is.character, ~"Yay") a <- if_else(.x = TRUE, .f = ~"Yay", .else = ~"Nay")
a <- if_then(1, is.numeric, ~"Yay") a <- if_not(1, is.character, ~"Yay") a <- if_else(.x = TRUE, .f = ~"Yay", .else = ~"Nay")
Is the element of class "try-error"?
is_try_error(.x)
is_try_error(.x)
.x |
the object to test |
A logical
x <- attempt(log("a"), silent = TRUE) is_try_error(x)
x <- attempt(log("a"), silent = TRUE) is_try_error(x)
This function behaves as 'on.exit()', but is run on error, and supports mappers.
on_error(f)
on_error(f)
f |
a function to call on error |
A local error handler.
y <- function(num) { on_error(~ write(Sys.time(), "error_log.txt", append = TRUE)) log(num) }
y <- function(num) { on_error(~ write(Sys.time(), "error_log.txt", append = TRUE)) log(num) }
A wrapper around silently and attempt
silent_attempt(...)
silent_attempt(...)
... |
the expression to evaluate |
an error if any, a warning if any.
## Not run: silent_attempt(warn("nop!")) ## End(Not run)
## Not run: silent_attempt(warn("nop!")) ## End(Not run)
silently returns a new function that will returns an error or a warning if any, or else returns nothing.
silently(.f)
silently(.f)
.f |
the function to silence |
an error if any, a warning if any. The result is never returned.
## Not run: silent_log <- silently(log) silent_log(1) silent_log("a") ## End(Not run)
## Not run: silent_log <- silently(log) silent_log(1) silent_log("a") ## End(Not run)
Friendlier messaging functions.
stop_if(.x, .p = isTRUE, msg = NULL) stop_if_any(.l, .p = isTRUE, msg = NULL) stop_if_all(.l, .p = isTRUE, msg = NULL) stop_if_none(.l, .p = isTRUE, msg = NULL) stop_if_not(.x, .p = isTRUE, msg = NULL) warn_if(.x, .p = isTRUE, msg = NULL) warn_if_any(.l, .p = isTRUE, msg = NULL) warn_if_all(.l, .p = isTRUE, msg = NULL) warn_if_none(.l, .p = isTRUE, msg = NULL) warn_if_not(.x, .p = isTRUE, msg = NULL) message_if(.x = NULL, .p = isTRUE, msg = NULL) message_if_any(.l, .p = isTRUE, msg = NULL) message_if_all(.l, .p = isTRUE, msg = NULL) message_if_none(.l, .p = isTRUE, msg = NULL) message_if_not(.x, .p = isTRUE, msg = NULL)
stop_if(.x, .p = isTRUE, msg = NULL) stop_if_any(.l, .p = isTRUE, msg = NULL) stop_if_all(.l, .p = isTRUE, msg = NULL) stop_if_none(.l, .p = isTRUE, msg = NULL) stop_if_not(.x, .p = isTRUE, msg = NULL) warn_if(.x, .p = isTRUE, msg = NULL) warn_if_any(.l, .p = isTRUE, msg = NULL) warn_if_all(.l, .p = isTRUE, msg = NULL) warn_if_none(.l, .p = isTRUE, msg = NULL) warn_if_not(.x, .p = isTRUE, msg = NULL) message_if(.x = NULL, .p = isTRUE, msg = NULL) message_if_any(.l, .p = isTRUE, msg = NULL) message_if_all(.l, .p = isTRUE, msg = NULL) message_if_none(.l, .p = isTRUE, msg = NULL) message_if_not(.x, .p = isTRUE, msg = NULL)
.x |
the element to evaluate. It can be a predicate function (i.e a function returning TRUE). |
.p |
the predicate with the condition to test on |
msg |
the message to return. If NULL (default), the built-in message is printed. |
.l |
the list of elements to evaluate |
## Not run: x <- 12 stop_if(x, ~ .x > 13) stop_if_not(x, is.character) a <- "this is not numeric" warn_if(a, is.character) warn_if_not(a, is.numeric) b <- 20 warn_if( b, ~ . > 10, msg = "Wow, that's a lot of b" ) c <- "a" message_if( c, is.character, msg = "You entered a character element" ) ## End(Not run)
## Not run: x <- 12 stop_if(x, ~ .x > 13) stop_if_not(x, is.character) a <- "this is not numeric" warn_if(a, is.character) warn_if_not(a, is.numeric) b <- 20 warn_if( b, ~ . > 10, msg = "Wow, that's a lot of b" ) c <- "a" message_if( c, is.character, msg = "You entered a character element" ) ## End(Not run)
Wrap a function in a try
surely(.f)
surely(.f)
.f |
the function to wrap |
an error if any, a warning if any, the result if any
## Not run: sure_log <- surely(log) sure_log(1) sure_log("a") ## End(Not run)
## Not run: sure_log <- surely(log) sure_log(1) sure_log("a") ## End(Not run)
Friendlier try catch functions
try_catch(expr, .e = NULL, .w = NULL, .f = NULL) try_catch_df(expr) map_try_catch(l, fun, .e = NULL, .w = NULL, .f = NULL) map_try_catch_df(l, fun)
try_catch(expr, .e = NULL, .w = NULL, .f = NULL) try_catch_df(expr) map_try_catch(l, fun, .e = NULL, .w = NULL, .f = NULL) map_try_catch_df(l, fun)
expr |
for simple try catch, the expression to be evaluated |
.e |
a one side formula or a function evaluated when an error occurs |
.w |
a one side formula or a function evaluated when a warning occurs |
.f |
a one side formula or an expression evaluated before returning or exiting |
l |
for map_* function, a list of arguments |
fun |
for map_* function, a function to try with the list |
try_catch handles errors and warnings the way you specify. 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.
## Not run: try_catch(log("a"), .e = ~ paste0("There was an error: ", .x)) try_catch(log(1), .f = ~ print("finally")) try_catch(log(1), .f = function() print("finally")) map_try_catch(list(1, 2, "a"), log, .e = ~ paste0("There was an error: ", .x)) map_try_catch_df(list(1, 2, "a"), log) ## End(Not run)
## Not run: try_catch(log("a"), .e = ~ paste0("There was an error: ", .x)) try_catch(log(1), .f = ~ print("finally")) try_catch(log(1), .f = function() print("finally")) map_try_catch(list(1, 2, "a"), log, .e = ~ paste0("There was an error: ", .x)) map_try_catch_df(list(1, 2, "a"), log) ## End(Not run)
with_message
and with_warning
add a warning or a message to a function.
without_message
and without_warning
turn the warning and message off.
with_message(.f, msg) with_warning(.f, msg) without_message(.f) without_warning(.f)
with_message(.f, msg) with_warning(.f, msg) without_message(.f) without_warning(.f)
.f |
the function to wrap |
msg |
the message to print |
a function
msg_as_num <- with_message(as.numeric, msg = "Numeric conversion") warn_as_num <- with_warning(as.numeric, msg = "Numeric conversion")
msg_as_num <- with_message(as.numeric, msg = "Numeric conversion") warn_as_num <- with_warning(as.numeric, msg = "Numeric conversion")