[Rd] using withCallingHandlers, how to deal with warning( , immediate. = TRUE)?
Philippe Grosjean
Philippe.Grosjean at umh.ac.be
Sun Jun 25 19:43:18 CEST 2006
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() ???
# ...?
More information about the R-devel
mailing list