Функция переключения в R: как выдать сообщение об ошибке или значение по умолчанию, если входные данные не совпадают?

#r #switch-statement

Вопрос:

Используя switch() в R, как я могу прервать с ошибкой, если вход в EXPR не определен внутри switch оператора?

Например, рассмотрим следующую функцию animal_sound() . Он принимает имя животного и возвращает звук, который издает животное.

 animal_sound <- function(x) {
  
  switch(x,
         "dog" = "woof",
         "cat" = "meow",
         "bee" = "bzzz",
         "duck" = "quack")
}
 

Пока животное определено внутри switch() , это работает.

 animal_sound("bee")
#> [1] "bzzz"
animal_sound("cat")
#> [1] "meow"
 

Но если мы передадим животное, которое не определено, возвращаемое значение будет пустым (даже не NULL ).

 animal_sound("alligator")
## nothing is printed to console
 

Есть ли способ либо выдать ошибку, либо установить возвращаемое значение по умолчанию в случае, если входные данные не совпадают?

Я мог бы сделать следующее, что является нежелательным решением:

 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.
 

Создано в 2021-10-18 годах пакетом reprex (v0.3.0)

Мне не нравится это решение, потому что оно требует вручную определить все возможные входные данные в начале. Это и глупо (учитывая, что мы определяем то же самое позже внутри switch() ), и подвержено ошибкам в случае, если я добавлю больше входных данных switch позже и могу забыть обновить valid_input вектор.

Существует ли элегантный/лаконичный способ вернуть информативное сообщение об ошибке в случае, если ввод не поддерживается?

Комментарии:

1. Из онлайн-документа: «В случае отсутствия совпадения, если есть неназванный элемент … его значение возвращается.». Разве это не позволяет вам вернуть, скажем, "Invalid" или другой флаг?

Ответ №1:

Вы можете добавить значение по умолчанию, подобное этому.

 animal_sound <- function(x) {
  
  switch(x,
         "dog" = "woof",
         "cat" = "meow",
         "bee" = "bzzz",
         "duck" = "quack",
         "default")
}
 

Комментарии:

1. Вы даже можете использовать stop("some error message") его по умолчанию.

Ответ №2:

Вы можете проверить аргументы с match.arg() помощью функции. Это приведет к появлению соответствующего сообщения об ошибке.

Это не менее подвержено ошибкам, но в данном случае это хорошая практика, так как аргумент может быть представлен в использовании {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")
}
 

Ответ №3:

Основываясь на ответе @Norie и комментарии @Roland, я немного доработал его.

 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
 

Создано в 2021-10-18 годах пакетом reprex (v0.3.0)