[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