<- function(x) {
err_even if ((x %% 2) == 0) {stop('Even numbers are error')} else {x}
}
Catching, passing, handling errors
There’s a lot out there on handling errors. This will mostly be testing things as they come up when I need to use them. Will rely heavily on Hadley, as usual.
Returning value or the error
I want to return the output value if something works, or the error message if it doesn’t. Let’s say in a list.
I don’t like how all the demos include an explicit stop()
call, somehow that confuses me. I’m going to do essentially the same thing, but bury it in a function, so it’s more like the behaviour we’d actually see.
As a test, what does that look over a vector? I’m going to loop so it’s clearer (maybe). And so I don’t get an error about asking about a vector in an if.
<- vector(mode = 'numeric', length = 10)
outvec for (i in 1:10) {outvec[i] <- err_even(i)}
Error in err_even(i): Even numbers are error
Try and passing
If we just use try
, the error should get printed but everything keeps moving
<- vector(mode = 'numeric', length = 10)
outvec for (i in 1:10) {outvec[i] <- try(err_even(i))}
Error in err_even(i) : Even numbers are error
Error in err_even(i) : Even numbers are error
Error in err_even(i) : Even numbers are error
Error in err_even(i) : Even numbers are error
Error in err_even(i) : Even numbers are error
outvec
[1] "1"
[2] "Error in err_even(i) : Even numbers are error\n"
[3] "3"
[4] "Error in err_even(i) : Even numbers are error\n"
[5] "5"
[6] "Error in err_even(i) : Even numbers are error\n"
[7] "7"
[8] "Error in err_even(i) : Even numbers are error\n"
[9] "9"
[10] "Error in err_even(i) : Even numbers are error\n"
Huh. I thought try
just printed the values but let things keep going. Changing the non-failures to character isn’t ideal. But I guess then I’d use tryCatch
? For now though, this is exactly what i need, so I’ll stop here.
tryCatch
I actually want to capture errors, warnings, or passing to assess some code
<- function(x) {
err_even_warn5 if ((x %% 2) == 0) {
stop('Even numbers are error')
else if (x == 5) {
} warning('5 throws a warning')
else {x}
} }
I want to use this for recording, so
<- vector(mode = 'character', length = 10)
recorder for (i in 1:10) {
<- tryCatch(err_even_warn5(i),
recorder[i] error = function(c) c$message,
warning = function(c) c$message,
message = function(c) c$message)
} recorder
[1] "1" "Even numbers are error" "3"
[4] "Even numbers are error" "5 throws a warning" "Even numbers are error"
[7] "7" "Even numbers are error" "9"
[10] "Even numbers are error"
And to be even more explicit, can I do some mods in the call to just say if it passed?
<- vector(mode = 'character', length = 10)
recorder2 for (i in 1:10) {
<- tryCatch(if(is.numeric(err_even_warn5(i))) {'pass'},
recorder2[i] error = function(c) c$message,
warning = function(c) c$message,
message = function(c) c$message)
} recorder2
[1] "pass" "Even numbers are error" "pass"
[4] "Even numbers are error" "5 throws a warning" "Even numbers are error"
[7] "pass" "Even numbers are error" "pass"
[10] "Even numbers are error"
Asides/specific cases
For purrr::map
and similar functions, we can use purrr::safely
and purrr::possibly
to pass errors without failing a whole run. The output then needs to be unpacked and cleaned up.
For foreach::foreach
, we can use the .errorhandling
argument to pass errors through without failing the whole run.