Skip to content

R: determine if `suppressMessages()` has been invoked

3 messages · Nino Hardt, Ivan Krylov, Simon Urbanek

#
Awesome, this gets the job done.
 
To answer your question:
When using C or C++ via Rinside or within a package, those functions do not listen to suppressMessages, e.g. `Rprintf` keeps printing to the console. Since it's common to use wrapper functions in R anyway, they can run `are_messages_suppressed` and pass the information on to an explicit `verbose` argument of the C / C++ function.
 
----- Original Mail -----
Von: "Ivan Krylov" <krylov.r00t at gmail.com>
An: "Nino Hardt" <me at ninohardt.com>
CC: r-devel at r-project.org
Gesendet: Sonntag, 19. Februar 2023 12:01:37
Betreff: Re: [Rd] R: determine if `suppressMessages()` has been invoked
On Sun, 19 Feb 2023 15:37:33 +0100 (CET)
Nino Hardt <me at ninohardt.com> wrote:
Would you mind letting us know why? Just curious. Normally, I would
just use message() for everything and let the users decide whether they
want to see it.
It works by cooperating with message().
message() itself works by trying to raise a "message" condition and
providing a "muffleMessage" restart that does nothing. If the condition
wasn't handled (the "muffleMessage" restart wasn't called by the
handler), the text of the message is printed.
In turn, suppressMessages() sets up a handler for conditions of class
"message" that invokes the "muffleMessage" restart provided by
message() itself above.
We can use the fact that the availability of the "muffleMessage"
restart is a documented detail and check whether signalling a "message"
condition will call this restart:
are_messages_suppressed <- function() withRestarts(
{
signalCondition(simpleMessage(''))
# we stay here if restart is not invoked
FALSE
},
muffleMessage = function()
# we jump here if restart is invoked
TRUE
)
are_messages_suppressed()
# [1] FALSE
suppressMessages(are_messages_suppressed())
# [1] TRUE
I don't think I understand handlers and restarts enough to explain them
well, but the following link seems to be one of the defining documents
for R's condition handling system:
https://homepage.stat.uiowa.edu/~luke/R/exceptions/simpcond.html
Hadley Wickham's Advanced R (first edition only) contains a good
explanation of R's condition system:
http://adv-r.had.co.nz/Exceptions-Debugging.html
http://adv-r.had.co.nz/beyond-exception-handling.html
(In my opinion, this could be a better question for R-help, since we
ought to be using documented R APIs here.)
#
On Sun, 19 Feb 2023 18:45:55 +0100 (CET)
Nino Hardt <me at ninohardt.com> wrote:

            
True, Rprintf is really convenient, but it doesn't raise any conditions
and just prints straight to the console. While calling R message() from
C is possible, it doesn't format anything.

There's a wishlist item for a C entry point for message() (I would
argue that a "messagef" taking a format string would be even better),
but it's waiting for someone with free time to implement it:
https://bugs.r-project.org/show_bug.cgi?id=17612
#
Nino,

that is the wrong way around as Ivan pointed out. Rprintf() is not the tool for this as explained. If you want messages, use them, it's easy to wrap it to C code:

static void Rmessage(const char *msg) {
    SEXP msg_sym = Rf_install("message");
    SEXP msg_call = PROTECT(lang2(msg_sym, PROTECT(Rf_mkString(msg))));
    Rf_eval(msg_call, R_BaseEnv);
    UNPROTECT(2);
}

or the f version if needed:

static void Rmessagef(const char *format, ...)
{
    char msg[512];
    va_list(ap);
    va_start(ap, format);
    if (vsnprintf(msg, sizeof(msg), format, ap) >= sizeof(msg))
        memcpy(msg + sizeof(msg) - 4, "...", 4);
    Rmessage(msg);
    va_end(ap);
}

Cheers,
Simon