2

I want to catch a warning and still run an expression.

Here is an example:

x <- 0
tryCatch({
  x <- as.numeric("text") # this is NA and causes warning
  }, warning = function(w) {
    print("I am a message")
})
x
# x still 0

Previous code catches the warning and print the message, BUT the value of x is not NA afterwards, which means that the expression did not run because of the warning.

I could run the expression with suppressWarnings() and <<- as follows:

x <- 0
tryCatch({
  x <- as.numeric("text")
  }, warning = function(w) {
    print("I am a message")
    suppressWarnings(x <<- as.numeric("text"))
})
x
# now x is NA

Is there a more elegant way to do that? maybe one of following examples?

  • another function other than tryCatch()
  • or using some parameter of tryCatch()
  • or maybe another package other than base
  • ...
Ferand Dalatieh
  • 313
  • 1
  • 4
  • 14
  • 2
    You might try `x <- purrr::quietly(as.numeric)("a")`, or some variant. It returns a list with the result and any errors, output or warnings. – joran Oct 04 '18 at 15:56

2 Answers2

0

From this answer follows that this code could work:

x <- 0
withCallingHandlers({
  x <- as.numeric("text")
  }, warning = function(w) {
    print("I am a message")
    invokeRestart("muffleWarning")
})
x

(I came across this post looking for a way to catch a warning and alter the return value of a function. I ended up with

which_nondefault_enc <- function(txt) {
    ans <- rep(NA, length(txt))
    for (i in seq(1, length(txt))) 
        ans[i] <- tryCatch(stringi::stri_enc_tonative(txt[i]), warning = function(w) return(NA))
    return(which(is.na(ans)))
}

which returns those indices of the vector, where warnings like "unable to translate '<U+0001F41F>' to native encoding" are used as a selection criterion.)

Karsten W.
  • 17,826
  • 11
  • 69
  • 103
0

Context I came up with a situation in which I need a more general condition handler that covers the scenarios of:

  • Handle a warning returning the return value of the function
  • Handle an error preventing the script from crashing

I came up with this not so much elegant solution:

Warning: Note that I'm using quosures in here because this is actually within an R6 class

handle_conditions <- function(expr) {
      withCallingHandlers({
        tryCatch({
          rlang::eval_tidy(expr)  
        }, error = function(cond) {
          handle_cond(cond)
        })
      }, warning = function(cond) {
        handle_cond(cond)
      })
    }

Usage

my_function <- function(x) {
 if (x > 5 & x <= 10) {
    warning("some warning message")
 } else if (x > 10) {
    stop("some error message")
 }
  x
}

handle_cond <- function(cond) {
  cat(cond$message)
}

rlang::quo(my_function(1)) |> handle_conditions()
# Raises a warning
rlang::quo(my_function(7)) |> handle_conditions()
# Raises an error
rlang::quo(my_function(20)) |> handle_conditions()

Do note that the idea behind evaluating with tryCatch without handling the warning is to cover these two cases, if we evaluate the expression and it catches an error then it will run the error handler. If the expression being evaluated raises a warning then it is not handled by the tryCatch but its handled by the withCallingHandlers. If it's not raising any of the specified conditions then it's just returning the return value of the expression.

Hope it helps

Fede Riva
  • 25
  • 6