[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