[Rd] suppress *specific* warnings?

Martin Maechler maechler at stat.math.ethz.ch
Thu Oct 25 11:28:23 CEST 2012


Sorry guys, for coming late,
but *please* don't go there.

I've been there years ago,
and found later why the approach is flawed "by design" :

Internationalization / Localization:

- If the warning comes from a "standard R" function,
  the warning is almost surely different in a (say) German
  locale, and your pattern won't be detected.

- Ditto if from a recommended package.

- If it is a warning that is not translated then it may be that
  it is just not *YET*  translated.

The really dangerous thing about matching error / warning
messages -- I had done it in the past with the error message I
caught via tryCatch() --
is that
- in your tests the code will work perfectly.
- on CRAN the code will work perfectly, as "they" also use
  the English (or C) locale.

So, by doing this you are distributing code that "almost always"
works ... in your environment if you are US, UK or similarly
based.

Indeed, a *really* dangerous practice.

Martin Maechler, ETH Zurich




>>>>> Martin Morgan <mtmorgan at fhcrc.org>
>>>>>     on Tue, 23 Oct 2012 05:28:48 -0700 writes:

    > On 10/22/2012 09:57 AM, luke-tierney at uiowa.edu wrote:
    >> On Sun, 21 Oct 2012, Martin Morgan wrote:
    >> 
    >>> On 10/21/2012 12:28 PM, Ben Bolker wrote:
    >>>> 
    >>>> Not desperately important, but nice to have and possibly of use to
    >>>> others, is the ability to suppress specific warnings rather than
    >>>> suppressing warnings indiscriminately.  I often know of a specific
    >>>> warning that I want to ignore (because I know that's it's a false
    >>>> positive/ignorable), but the current design of suppressWarnings() forces
    >>>> me to ignore *any* warnings coming from the expression.
    >>>> 
    >>>> I started to write a new version that would check and, if supplied
    >>>> with a regular expression, would only block matching warnings and
    >>>> otherwise would produce the warnings as usual, but I don't quite know
    >>>> enough about what I'm doing: see ??? in expression below.
    >>>> 
    >>>> Can anyone help, or suggest pointers to relevant
    >>>> examples/documentation (I've looked at demo(error.catching), which isn't
    >>>> helping me ... ?)
    >>>> 
    >>>> suppressWarnings2 <- function(expr,regex=NULL) {
    >>>> opts <- options(warn = -1)
    >>>> on.exit(options(opts))
    >>> 
    >>> I'm not really sure what the options(warn=-1) is doing there, maybe its for
    >>> efficiency to avoid generating a warning message (as distinct from signalling
    >> 
    >> The sources in srs/library/base/conditions.R have
    >> 
    >> suppressWarnings <- function(expr) {
    >> ops <- options(warn = -1) ## FIXME: temporary hack until R_tryEval
    >> on.exit(options(ops))     ## calls are removed from methods code
    >> withCallingHandlers(expr,
    >> warning=function(w)
    >> invokeRestart("muffleWarning"))
    >> }
    >> 
    >> I uspect we have still not entirely eliminated R_tryEval in this context
    >> but I'm not sure. Will check when I get a chance.
    >> 
    >>> a warning). I think you're after something like
    >>> 
    >>> suppressWarnings2 <-
    >>> function(expr, regex=character())
    >>> {
    >>> withCallingHandlers(expr, warning=function(w) {
    >>> if (length(regex) == 1 && length(grep(regex, conditionMessage(w)))) {
    >>> invokeRestart("muffleWarning")
    >>> }
    >>> })
    >>> }
    >> 
    >> A problem with using expression matching is of course that this fails
    >> with internationalized messages. Ideally warnings should be signaled as
    >> warning conditions of a particular class, and that class can be used
    >> to discriminate. Unfortunately very few warnings are designed this way.

    > Probably specific messages, rather than patterns, would be handled and then

    > suppressWarnings2 <- function(expr, messages = character())
    > {
    > opts <- options(warn = -1)
    > on.exit(options(ops))
    > withCallingHandlers(expr, warning=function(w) {
    > if (conditionMessage(w) %in% messages)
    > invokeRestart("muffleWarning")
    > })
    > }

    > gives one the illusion of speaking many languages

    > suppressWarnings2(log(-1), gettext("NaNs introduced", domain="R"))

    > Martin

    >> 
    >> Best,
    >> 
    >> luke
    >> 
    >>> 
    >>> If the  restart isn't invoked, then the next handler is called and the warning
    >>> is handled as normal. So with
    >>> 
    >>> f <- function() {
    >>> warning("oops")
    >>> 2
    >>> }
    >>> 
    >>> there is
    >>> 
    >>>> suppressWarnings2(f())
    >>> [1] 2
    >>> Warning message:
    >>> In f() : oops
    >>>> suppressWarnings2(f(), "oops")
    >>> [1] 2
    >>> 
    >>> For your own code I think a better strategy is to create a sub-class of
    >>> warnings that can be handled differently
    >>> 
    >>> mywarn <-
    >>> function(..., call.=TRUE, immediate.=FALSE, domain=NULL)
    >>> {
    >>> msg <- .makeMessage(..., domain=domain, appendLF=FALSE)
    >>> call <- NULL
    >>> if (call.)
    >>> call <- sys.call(1L)
    >>> class <- c("silencable", "simpleWarning",  "warning", "condition")
    >>> cond <- structure(list(message=msg, call=call), class=class)
    >>> warning(cond)
    >>> }
    >>> 
    >>> suppressWarnings3 <-
    >>> function(expr)
    >>> {
    >>> withCallingHandlers(expr, silencable=function(w) {
    >>> invokeRestart("muffleWarning")
    >>> })
    >>> }
    >>> 
    >>> then with
    >>> 
    >>> g <- function() {
    >>> mywarn("oops")
    >>> 3
    >>> }
    >>> 
    >>>> suppressWarnings3(f())
    >>> [1] 2
    >>> Warning message:
    >>> In f() : oops
    >>>> g()
    >>> [1] 3
    >>> Warning message:
    >>> In g() : oops
    >>>> suppressWarnings3(g())
    >>> [1] 3
    >>> 
    >>>> withCallingHandlers(expr, warning = function(w) {
    >>>> ## browser()
    >>>> if (is.null(regex) || grepl(w[["message"]],regex)) {
    >>>> invokeRestart("muffleWarning")
    >>>> } else {
    >>>> ## ? what do I here to get the warning issued?
    >>>> ## browser()
    >>>> ## computeRestarts() shows "browser",
    >>>> ##    "muffleWarning", and "abort" ...
    >>>> options(opts)
    >>>> warning(w$message)
    >>>> ## how can I get back from here to the calling point
    >>>> ##   *without* muffling warnings ... ?
    >>>> }
    >>>> })
    >>>> }
    >>>> 
    >>>> suppressWarnings2(sqrt(-1))
    >>>> suppressWarnings2(sqrt(-1),"abc")
    >>>> 
    >>>> It seems to me I'd like to have a restart option that just returns to
    >>>> the point where the warning was caught, *without* muffling warnings ...
    >>>> ?  But I don't quite understand how to set one up ...
    >>>> 
    >>>> Ben Bolker
    >>>> 
    >>>> ______________________________________________
    >>>> R-devel at r-project.org mailing list
    >>>> https://stat.ethz.ch/mailman/listinfo/r-devel
    >>>> 
    >>> 
    >>> 
    >>> 
    >> 


    > -- 
    > Computational Biology / Fred Hutchinson Cancer Research Center
    > 1100 Fairview Ave. N.
    > PO Box 19024 Seattle, WA 98109

    > Location: Arnold Building M1 B861
    > Phone: (206) 667-2793

    > ______________________________________________
    > R-devel at r-project.org mailing list
    > https://stat.ethz.ch/mailman/listinfo/r-devel



More information about the R-devel mailing list