purrr icon indicating copy to clipboard operation
purrr copied to clipboard

[FR] add the condition class in the output of quietly()

Open DanChaltiel opened this issue 3 years ago • 0 comments

Hi,

It would be very convenient if the value returned in $warning and $message was the actual condition instead of only the text message when using quietly() (or, in an exciting future, when using what is suggested in https://github.com/tidyverse/purrr/issues/426 and https://github.com/tidyverse/purrr/pull/725).

Indeed, as read in the book "Advanced R":

One of the challenges of error handling in R is that most functions generate one of the built-in conditions, which contain only a message and a call. That means that if you want to detect a specific type of error, you can only work with the text of the error message. This is error-prone, not only because the message might change over time, but also because messages can be translated into other languages.

This is particularly true for errors, hence the returned value of safely() is the whole error.

However, using quietly() only returns the condition message. For instance, consider this example:

f = function(x){
    if(x<100){
        rlang::warn("x is lesser than 100", 
                    class="low_x")
    }
    if(x>1000){
        rlang::warn("x is higher than 1000", 
                    class="high_x")
    }
    x
}

quiet_f = purrr::quietly(f)

x = quiet_f(50)
class(x$warnings)
#> [1] "character"

#for now, I need to parse the message
if(stringr::str_detect("higher", x$warnings)){
    #do something
}

#instead, I'd like to be able to write:
if(inherits(x$warnings, "high_x")){
    #do something
}

Created on 2021-10-23 by the reprex package (v2.0.1)

Of course, I should have considered the case where x$warnings is a list of several warnings but I wanted to keep this example it simple.

However, while I really think all of this would make more sense, it might lead to breaking changes if some existing code is expecting a character value. A workaround would be to add the class as an attribute of the character value:

if("high_x" %in% attr(x$warnings, "w_class")){
    #do something
}

DanChaltiel avatar Oct 23 '21 17:10 DanChaltiel