r4ds / bookclub-Advanced_R

164 stars 52 forks source link

add QA on using tryCatch (ch8/conditions) #202

Open tanho63 opened 4 years ago

tanho63 commented 4 years ago

Saving a QA from Slack for later bookdowning Q

Had a quick question about tryCatch and my mental model of how a tryCatch condition would work. Natively coming into R I would try to write a tryCatch like this:

test_func <- function(x) {
    tryCatch(
        new_value = log(x),
        error = function(cnd){
            cat("That's not a number!!!")
            new_value = NA_integer_
        } 
    )
    return(new_value)
}

Obviously this does not work as expected Instead we should write functions to test our code like this?

my_error_catcher <- function(expr) {
    tryCatch(
        error = function(cnd){
            cat("That's not a number!\n")
            NA_integer_
            },
        {
            expr
        }
    )
}
test_func <- function(x){
    new_value = my_error_catcher(log(x))
    return(new_value)
} 

A:

I think your problem is more like...

test_func <- function(x) {
  value <-  tryCatch(
    log(x),
    error = function(e){
      cat("That's not a number! Returning NA_int")
      NA_integer_
    } 
  )
  return(value)
}

In your first attempt, the R interpreter was reading log(x) as an argument to the tryCatch function called new_value rather than reading it as an expr to evaluate, which is why your error function wasn't being triggered you could theoretically wrap the expression in curly braces so that it's treated as an expression - ie

test_func <- function(x) {
  tryCatch(
    {new_value = log(x)},
    error = function(cnd){
      cat("That's not a number!!!")
      new_value = NA_integer_
    } 
  )
  return(new_value)
}

which will correctly trigger the error function - but the error function suffers from an environment issue where the new_value is not being assigned in the correct function environment