Using switch() in R, how can I abort with error if the input to EXPR is not defined inside the switch statement?
For example, consider the following function animal_sound(). It accepts an animal name and returns the sound the animal makes.
animal_sound <- function(x) {
switch(x,
"dog" = "woof",
"cat" = "meow",
"bee" = "bzzz",
"duck" = "quack")
}
As long as the animal is defined within switch(), this works.
animal_sound("bee")
#> [1] "bzzz"
animal_sound("cat")
#> [1] "meow"
But if we pass an animal that isn't defined, the return value is blank (not even NULL).
animal_sound("alligator")
## nothing is printed to console
Is there a way to either throw an error or set a default return value in case the input has no match?
I could have done the following, which is an undesired solution:
animal_sound_with_error_message <- function(x) {
valid_input_animals <- c("dog", "cat", "bee", "duck")
input_is_valid <- any(x %in% valid_input_animals)
if (!input_is_valid) {
stop("animal is not supported. Try a different animal.")
}
switch(x,
"dog" = "woof",
"cat" = "meow",
"bee" = "bzzz",
"duck" = "quack")
}
animal_sound_with_error_message("bee")
#> [1] "bzzz"
animal_sound_with_error_message("cat")
#> [1] "meow"
animal_sound_with_error_message("alligator")
#> Error in animal_sound_with_error_message("alligator"): animal is not supported. Try a different animal.
Created on 2021-10-18 by the reprex package (v0.3.0)
I dislike this solution because it requires to manually define all possible input in the beginning. It is both silly (given that we define the same later inside switch()) and error-prone in case I add more inputs to switch later on, and may forget to update the valid_input vector.
Is there an elegant/concise way to return an informative error message in case the input isn't supported?
You can check the arguments with the match.arg() function. This will generate an appropriate error message.
It not less error prone, but in this case it's a good practice since the argument can be presented in usage by {Roxygen}.
animal_sound_with_error_message <- function(x = c("dog", "cat", "bee", "duck")) {
match.arg(x)
switch(x,
"dog" = "woof",
"cat" = "meow",
"bee" = "bzzz",
"duck" = "quack")
}
You can add a default like this.
animal_sound <- function(x) {
switch(x,
"dog" = "woof",
"cat" = "meow",
"bee" = "bzzz",
"duck" = "quack",
"default")
}
Based on @Norie's answer and @Roland's comment, I've tailored it a bit further.
animal_sound <- function(x) {
my_error <- rlang::abort(paste(x, "isnt supported", sep = " "))
switch(x,
"dog" = "woof",
"cat" = "meow",
"bee" = "bzzz",
"duck" = "quack",
my_error)
}
animal_sound("crocodile")
#> Error: crocodile isnt supported
Created on 2021-10-18 by the reprex package (v0.3.0)