From pdalgd at gmail.com  Fri Oct 26 13:04:24 2012
From: pdalgd at gmail.com (peter dalgaard)
Date: Fri, 26 Oct 2012 13:04:24 +0200
Subject: [Rd] suppress *specific* warnings?
In-Reply-To: <20618.21822.411471.735141@stat.math.ethz.ch>
References: <50844CC3.6020302@ufl.edu> <50849C77.6050106@fhcrc.org>
	<alpine.LFD.2.02.1210221153530.1869@nokomis.stat.uiowa.edu>
	<50868D80.10308@fhcrc.org>
	<20617.1591.947596.745192@stat.math.ethz.ch>
	<508919AD.3090205@gmail.com>
	<20618.21822.411471.735141@stat.math.ethz.ch>
Message-ID: <5809ACD3-8FE3-4F57-AD7C-604DF82D8981@gmail.com>


On Oct 26, 2012, at 11:17 , Martin Maechler wrote:

>>>>>> Duncan Murdoch <murdoch.duncan at gmail.com>
>>>>>>    on Thu, 25 Oct 2012 06:51:25 -0400 writes:
> 
>> On 12-10-25 5:28 AM, Martin Maechler wrote:
>>> 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.
> 
>> I think the other Martin's suggestion addressed this:  he matched the 
>> translated message, not the English original.
> 
>> Duncan Murdoch
> 
> Well, I don't think I understand.
> Of course you can only match "the message" that  warning() or
> error()  {or rather tryCatch() ,...}  produces.
> But you cannot guarantee nor know (for sure) if that message is 'original'
> or translated.
> "cannot", because AFAIK
> we cannot guarantee  Sys.setlocale() is obeyed platform
> independently:
> You would have to query the current and save that, set it to C, get the
> message, and then reset the locale to the previously saved one.
> And these do not work reliably, on some platforms, AFAIK and
> read our documentation.

I think the point was to use gettext() on the pattern-to-match. If the warning is translated, so would this be. The main limitations would seem to be that you have to be d*mn sure to get the spelling right and, presumably, it only works with straight string translations, not variant forms like

     msgid "found %d fatal error"
     msgid_plural "found %d fatal errors"
     msgstr[0] "s'ha trobat %d error fatal"
     msgstr[1] "s'han trobat %d errors fatals"




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

-- 
Peter Dalgaard, Professor
Center for Statistics, Copenhagen Business School
Solbjerg Plads 3, 2000 Frederiksberg, Denmark
Phone: (+45)38153501
Email: pd.mes at cbs.dk  Priv: PDalgd at gmail.com



[Rd] suppress *specific* warnings?
peter dalgaard