##================================================================## ### In longer simulations, aka computer experiments, ### ### you may want to ### ### 1) catch all errors and warnings (and continue) ### ### 2) store the error or warning messages ### ### ### ### Here's a solution (see R-help mailing list, Dec 9, 2010): ### ##================================================================## ##' Catch *and* save both errors and warnings, and in the case of ##' a warning, also keep the computed result. ##' ##' @title tryCatch both warnings (with value) and errors ##' @param expr an \R expression to evaluate ##' @return a list with 'value' and 'warning', where ##' 'value' may be an error caught. ##' @author Martin Maechler; ##' Copyright (C) 2010-2023 The R Core Team tryCatch.W.E <- function(expr) { W <- NULL w.handler <- function(w) { # warning handler W <<- w invokeRestart("muffleWarning") } list(value = withCallingHandlers(tryCatch(expr, error = function(e) e), warning = w.handler), warning = W) } str( tryCatch.W.E( log( 2 ) ) ) str( tryCatch.W.E( log( -1) ) ) str( tryCatch.W.E( log("a") ) ) ##' @title Catch *all* warnings and the value ##' @param expr an \R expression to evaluate ##' @return a list with 'value' and 'warnings' ##' @author Luke Tierney (2004), R-help post ##' https://stat.ethz.ch/pipermail/r-help/2004-June/052132.html withWarnings <- function(expr) { W <- NULL wHandler <- function(w) { W <<- c(W, list(w)) invokeRestart("muffleWarning") } val <- withCallingHandlers(expr, warning = wHandler) list(value = val, warnings = W) } withWarnings({ warning("first"); warning("2nd"); pi }) r <- withWarnings({ log(-1) + sqrt(-4); exp(1) }) str(r, digits=14) ##' @title tryCatch *all* warnings and messages, and an error or the final value ##' @param expr an \R expression to evaluate ##' @return a list with `messages`, `warnings`, and ##' `value` which may be an error caught. ##' @author Martin Maechler (combining the above) tryCatch_WEMs <- function(expr) { W <- M <- NULL w.handler <- function(w) { # warning handler W <<- c(W, list(w)); invokeRestart("muffleWarning") } m.handler <- function(m) { # message handler M <<- c(M, list(m)); invokeRestart("muffleMessage") } list(value = withCallingHandlers(tryCatch(expr, error = function(e) e), warning = w.handler, message = m.handler), messages = M, warnings = W) } f3 <- function(x) { r <- log(-x) + sqrt(-x) # produce warnings when x >= 0 if(anyNA(r)) message(sprintf("%d NA's produced by log(.) + sqrt(.)", sum(is.na(r)))) r <- exp(-x) if(any(ii <- is.infinite(r))) message(sprintf("Got +/- Inf from x[%s]", deparse(which(ii)))) r } str( r0 <- tryCatch_WEMs(f3("A")) ) # just an error from '-x' stopifnot(exprs = { inherits (r0$value, "error") identical(r0$value$call, quote(-x)) sapply(r0[c("messages","warnings")], is.null) }) (x <- c(-1:1, (-1:1)/0)) str( rI <- tryCatch_WEMs(f3(x) )) stopifnot(exprs = { identical(lengths(rI), c(value = length(x), messages = 2L, warnings = 2L)) rI$value[4] == Inf all.equal(rI$value, exp(-x)) length(rI$messages) == 2; sapply(rI$messages, inherits, what="message") length(rI$warnings) == 2; sapply(rI$warnings, inherits, what="warning") })