Print vector in friendly error message


#1

Hi all,

I have a function that takes a vector. Under some conditions (i.e. an invalid vector), I want to throw an error (stop("...")).

I want to raise an error message that contains a copy-paste-friendly representation of the vector that was input. Ideally something like:

my_invalid_input <- c("a", 1, "c")
my_function(my_invalid_input)
#> Error in my_function(my_invalid_input): Invalid subset c("a", 1, "c")

I can get close with something like

my_function <- function(x) {
 
  ...

  if (is_invalid(x)) {
    x_str <- glue::collapse(x, ", ")
    stop(glue::glue("Invalid subset c({x_str})"))

  ...

}
#> Error in my_function(my_invalid_input): Invalid subset c(a, 1, c)

But this still isn't pasteable (lack of quotation marks).

My questions boil down to:

  • Is this a worthwhile idea? Or are there better practices for error messages in R (if so - where can I find out more about them)?
  • Is this possible? And how would I go about doing this?

In the latter case, it seems like rlang or lazyeval might be useful?


#2

There is some work already being done on defensive programming. For example, here is one package and in its README you also have multiple alternatives of how you can achieve your goal.


#3

a combination of dput and capture.output ought to work. For example:

some_function <- function(x){
  if (TRUE){
    x_str <- capture.output(dput(x))
    stop(glue::glue("Invalid subset {x_str}"))
  }
}

some_function(letters[1:5])

Error in some_function(letters[1:5]) :
Invalid subset c("a", "b", "c", "d", "e")

As an alternative, I have a strong preference for the checkmate package. Your function might look something like this with checkmate

other_function <- function(x){
  checkmate::assert_subset(x = x,
                           choices = letters)
}

other_function(c("a", 1, "c"))

Error in other_function(c("a", 1, "c")) :
Assertion on 'x' failed: Must be a subset of
{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}.