[Rd] using withCallingHandlers, how to deal with warning( , immediate. = TRUE)?

Philippe Grosjean phgrosjean at sciviews.org
Tue Jun 27 15:48:59 CEST 2006


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 at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>



More information about the R-devel mailing list