iago
iago

Reputation: 3256

Is it possible to handle simple messages in R? If yes, how?

To handle warnings or errors one can use

result = tryCatch({
    expr
}, warning = function(w) {
    warning-handler-code
}, error = function(e) {
    error-handler-code
}, finally = {
    cleanup-code
}

but if expr gives a message through simpleMessage, how can I get it? Is there something like?:

message = function(m) {message-handler-code}

Or another function which allows me to capture the message?

Thank you!

Upvotes: 0

Views: 337

Answers (2)

Konrad Rudolph
Konrad Rudolph

Reputation: 545518

tryCatch is the most commonly useful solution for handling conditions.

However, tryCatch aborts execution and returns the value of the handler, rather than resuming execution of the code. This may not always be what you want; sometimes you want to handle a condition and carry on.

R allows this thanks to its incredibly powerful condition system.

For example, you can choose to silence all messages:

suppressMessages(expr)

The nice thing here is that the suppressMessages isn’t magic — it’s a plain old R function and you could write it yourself (but you do need to understand the condition system, and the price for its versatility is that it’s fairly complicated).

To illustrate this, here’s another way of handling messages — using withCallingHandlers — which suppresses the messages, carries on executing the code it’s called with, but at the same time logs the message in a list:

messages = list()

withCallingHandlers({
    message('Hello world')
    1 + 1
}, message = function (msg) {
    messages <<- c(messages, msg)
    tryInvokeRestart('muffleMessage')
})

tryInvokeRestart('muffleMessage') is the same method by which suppressMessages works. The only difference is that we added code to store the message.

As a last step, the above can even be wrapped inside a function:

with_logging = function (expr) {
    messages = list()

    log_message = function (msg) {
        messages <<- c(messages, conditionMessage(msg))
        tryInvokeRestart('muffleMessage')
    }

    result = withCallingHandlers(expr, message = log_message)
    list(result = result, messages = messages)
}

And to use it:

with_logging({
    message('this is a test')
    1 + 1
})
$result
[1] 2

$messages
$messages[[1]]
[1] "this is a test\n"

Upvotes: 2

Allan Cameron
Allan Cameron

Reputation: 173793

Yes, you can use message = just as you can with warning and error:

result = tryCatch({
    message("Hello world")
    1 + 1
}, message = function(m) {m}
)

result
#> <simpleMessage in message("Hello world"): Hello world
>

It's more likely however that you would want to capture your result and message separately:

result <- withCallingHandlers({
    message("Hello world")
    1 + 1
}, message = function(m) {
    lastMessage <<- m
    invokeRestart("muffleMessage")
})

result
#> [1] 2

if(exists("lastMessage")) message(lastMessage)
#> Hello world

Upvotes: 3

Related Questions