Luke Tierney wrote: > I don't think there is currently any way of identifying the > immediate. = TRUE calls short of walking up the call stack with the > appropriate sys.xyz functions. A better design would have been for > calls with immediate. = TRUE to signal warnings of a subclass of > simpleWarning, say immediateSimpleWarning, so these can be caught and > handled more reasonably. I'll make a note to look into this.
Yes, that would be wonderful! Best, Philippe > Best, > > luke > > > On Sun, 25 Jun 2006, Philippe Grosjean wrote: > >> Hello, >> >> I want to use withCallingHandlers(expr, warning = function(w) { ....}), >> that is, to use a custom warning handler. I want this handler to >> replicate the behavior of the usual handler. I have problems with the >> mode 'options(warn = 0)' where the warnings are delayed, except if >> calling 'warning("message", immediate. = TRUE). Indeed, if my custom >> warning handler manages to delay the display of warning messages, it >> cannot detect if the argument immediate. = TRUE was use, and thus, it >> cannot behave consequently. >> >> Here is a toy example to illustrate my problem (whole script at the end >> of this message): >> >> > # This is what I want to replicate in my own handler: >> > options(warn = 0) >> > options(warning.expression = NULL) >> > for (i in 1:3) { >> + print(i) >> + warning("test", immediate. = (i < 2)) >> + } >> [1] 1 >> Warning: test >> [1] 2 >> [1] 3 >> Warning messages: >> 1: test >> 2: test >> # First warning is NOT delayed, but the others are >> >> Here is what I could use if I do not delay printing of warnings: >> >> > options(warning.expression = NULL) >> > options(warning.expression = expression()) # Disable normal warnings >> > withCallingHandlers(for (i in 1:3) {print(i); >> + warning("test", immediate. = (i < 2))}, >> + warning = function(w) >> + cat("Warning:", conditionMessage(w), "\n")) >> [1] 1 >> Warning: test >> [1] 2 >> Warning: test >> [1] 3 >> Warning: test >> > options(warning.expression = NULL) >> >> It gets a little bit more complex to delay handling of warning messages, >> but basically, I manage it that way: >> >> > options(warning.expression = NULL) >> > options(warning.expression = NULL) >> > options(warning.expression = expression()) # Disable normal warnings >> > if (exists("last.warning", envir = .GlobalEnv)) >> + rm("last.warning", envir = .GlobalEnv) >> > withCallingHandlers(for (i in 1:3) {print(i); >> + warning("test", immediate. = (i < 2))}, >> + warning = function(w) { >> + if (exists("last.warning", envir = .GlobalEnv)) { >> + lwarn <- get("last.warning", envir = .GlobalEnv) >> + } else lwarn <- list() >> + # Do not add more than 50 warnings >> + if (length(lwarn) >= 50) return() >> + # Add the warning to this list >> + nwarn <- length(lwarn) >> + names.warn <- names(lwarn) >> + Call <- conditionCall(w) >> + lwarn[[nwarn + 1]] <- Call >> + names(lwarn) <- c(names.warn, conditionMessage(w)) >> + # Save the modified version in .GlobalEnv >> + last.warning <<- lwarn >> + }) >> [1] 1 >> [1] 2 >> [1] 3 >> > invisible(warnings()) # Now display delayed warnings() >> Warning messages: >> 1: test in: withCallingHandlers(for (i in 1:3) { ... >> 2: test in: withCallingHandlers(for (i in 1:3) { ... >> 3: test in: withCallingHandlers(for (i in 1:3) { ... >> > options(warning.expression = NULL) >> >> Now, obviously, I need a mechanism to detect if 'immediate. = TRUE' was >> used in warning(), in order to delay or not accordingly, and replicate >> exactly the example above... BUT... I have no idea at all where I can >> find this information! Could someone help me, please? >> Best, >> >> Philippe Grosjean >> >> P.S.: here is the complete script of the toy example: >> >> ### The example we want to replicate with our own handler >> options(warn = 0) >> options(warning.expression = NULL) >> for (i in 1:3) { >> print(i) >> warning("test", immediate. = (i < 2)) >> } >> >> ### A custom warning handler that does NOT delay warning messages >> options(warning.expression = NULL) >> options(warning.expression = expression()) # Disable normal warnings >> withCallingHandlers(for (i in 1:3) {print(i); >> warning("test", immediate. = (i < 2))}, >> warning = function(w) >> cat("Warning:", conditionMessage(w), "\n")) >> options(warning.expression = NULL) >> >> ### A custom warning handler that ALWAYS delays warning messages >> options(warning.expression = NULL) >> options(warning.expression = expression()) # Disable normal warnings >> if (exists("last.warning", envir = .GlobalEnv)) >> rm("last.warning", envir = .GlobalEnv) >> withCallingHandlers(for (i in 1:3) {print(i); >> warning("test", immediate. = (i < 2))}, >> warning = function(w) { >> if (exists("last.warning", envir = .GlobalEnv)) { >> lwarn <- get("last.warning", envir = .GlobalEnv) >> } else lwarn <- list() >> # Do not add more than 50 warnings >> if (length(lwarn) >= 50) return() >> # Add the warning to this list >> nwarn <- length(lwarn) >> names.warn <- names(lwarn) >> Call <- conditionCall(w) >> lwarn[[nwarn + 1]] <- Call >> names(lwarn) <- c(names.warn, conditionMessage(w)) >> # Save the modified version in .GlobalEnv >> last.warning <<- lwarn >> }) >> invisible(warnings()) # Now display delayed warnings() >> options(warning.expression = NULL) >> >> ### How do I write my handler that delays only when warn = 0 and >> ### immediate. = FALSE in the calling of warning() ??? >> # ...? >> >> ______________________________________________ >> R-devel@r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel >> > ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel