Have anyone seen a good implementation of a function that works like on.exit but for errors? A on.error or if.error if you like. So in a function it would look something like this below:
I'm not looking for a tryCatch function as I'd like to avoid wrapping all of my code into that.
Here is some dummy code that doesn't work, but sort of gives an idea:
on_error <- function(x = returnValue()){
tryCatch(expr = {
message("eval expr")
x},
error = function(e){
message("error")
stop(e)
}
)
}
test_function <- function(x){
on.exit(on_error())
log(x)
}
test_function(1) # should work
test_function("a") # I need this to eval the error part in on_error
You want a function that executes some operation, say log(), so that, if there is no error in running log(), you just return the result, but if there is an error in running log(), you run the alternative function on_error(), is that the idea?
If so, why are you not happy with:
main_function <- log
on_error <- function(e){
message("There was an error:\n", e,"But we caught it")
}
test_function <- function(x){
tryCatch(main_function(x),
error = on_error)
}
test_function(1)
#> [1] 0
test_function("a")
#> There was an error:
#> Error in main_function(x): non-numeric argument to mathematical function
#> But we caught it
The wrapping in tryCatch() doesn't look like much overhead, why is it a problem? Considering you can always leave the actual code in main_function(). Or if you want to make it even more transparent:
I agree that on the surface it doesn't look like there is a lot of overhead, but I have 26 packages that scrape all sorts of different sites from docker on DigitalOcean. I would like a one line solution I can add to the top of most of the functions, so I can get a message on telegram when there is an error. I still want the functions to fail like they would do under normal circumstances though. I think a solution similar to on.exit or on.exit(on_error())would be a simple and clean way to handle it.
I've ended up with the solution below, even though I see it's not really recommended in the comments on SO.
Inspired by:
call_this_function_to_see_if_the_function_failed <- function() {
if (exists(".Traceback", envir = globalenv())) {
traceback_calls <- get(".Traceback", envir = globalenv())
sys_calls <- sys.calls()
# Check if the most recent call in the traceback is the current function call
if (identical(sys_calls[[length(sys_calls)]], traceback_calls[[1]])) {
message("An error occurred in my_function.")
} else {
message("The detected error is not related to my_function.")
}
} else {
message("No error detected.")
}
}
my_function <- function(x) {
on.exit(call_this_function_to_see_if_the_function_failed(), add = TRUE)
log(x)
}
# Example usage
my_function(1) # Should not produce an error
my_function("a") # Will cause an error
There should never be a NULL returned in those functions, so this is probably not a bad idea for my use case. I think I'll go with this one, as I don't risk running into issues with .Traceback.