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 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")
}
})
}
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