[Rd] using withCallingHandlers, how to deal with warning( , immediate. = TRUE)?
Luke Tierney
luke at stat.uiowa.edu
Tue Jun 27 15:26:31 CEST 2006
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.
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 at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>
--
Luke Tierney
Chair, Statistics and Actuarial Science
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa Phone: 319-335-3386
Department of Statistics and Fax: 319-335-3017
Actuarial Science
241 Schaeffer Hall email: luke at stat.uiowa.edu
Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu
More information about the R-devel
mailing list