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?
CodePudding user response:
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")
}
CodePudding user response:
You can add a default like this.
animal_sound <- function(x) {
switch(x,
"dog" = "woof",
"cat" = "meow",
"bee" = "bzzz",
"duck" = "quack",
"default")
}
CodePudding user response:
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)