0
votes

I'm pretty new to writing functions in r. I've come up with a sample function. I'm looking for help with the following:

  • I have a function that has character choices that can be one of a selection of specific choices
  • I want to check that the choice is a part of that character vector of choices (without title case mattering)
  • I'd also like to use glue::glue if possible so that I can be more specific with my error message. Example below.

Can you also show me the difference in code to write errors if only 1 choice is allowed in the character vector, or more than one choice is allowed?

library(stringr)

sample_function <- function(choice = c("apples", "bananas", "cherries")) {

allowed_choices <- c("apples", "bananas", "cherries")


# match to lowercase 
choice <- str_to_lower(choice)

if(!choice %in% allowed_choices){
  stop("Please choose Apples, Bananas, or Cherries")
}

}

sample_function(choice = "Test")
#> Error in sample_function(choice = "Test"): Please choose Apples, Bananas, or Cherries
Created on 2019-11-18 by the reprex package (v0.3.0)

Can I do something like the below in the stop message. I'd want the character vector to be separated by commas:

glue::glue("{choice} is not a valid choice.  Please choose from: {allowed_choices}")
3

3 Answers

1
votes

There is a glue function glue_collapse for collapsing vectors like this with an "or" (or something else) before the last element

sample_function <- function(choice = c("apples", "bananas", "cherries")) {

  allowed_choices <- c("apples", "bananas", "cherries")
  allowed_choices_coll <- glue_collapse(allowed_choices, sep = ', ', last = ' or ')

  # match to lowercase 
  choice <- str_to_lower(choice)
  if(!choice %in% allowed_choices){
    stop(
      glue::glue("{choice} is not a valid choice.  Please choose from: {allowed_choices_coll}")
    )
  }

}

sample_function(choice = 'mango')

# Error in sample_function(choice = "mango") : 
#   mango is not a valid choice.  Please choose from: apples, bananas or cherries
0
votes

I tend to do something like the following:

sample_function <- function(choice = c("apples", "bananas", "cherries")) {
  allowed_choices <- c("apples", "bananas", "cherries")

  extra_choices <- setdiff(choice, allowed_choices)
  if (length(extra_choices)) {
    stop("unrecognized 'choice': ", paste(sQuote(extra_choices), collapse = ","))
    # optional alternative
    stop("'choice' must be from ", paste(sQuote(allowed_choices), collapse = ","))
  }
}

assuming that you are allowing more than one choice.

Whether you use glue or not is up to you, but the paste(..., collapse) thing might be useful.

0
votes

We can collapse with str_c from stringr and use that in the glue

library(stringr)

sample_function <- function(choice = c("apples", "bananas", "cherries")) {

allowed_choices <- c("apples", "bananas", "cherries")


# match to lowercase 
choice <- str_to_lower(choice)

concat_choices <- str_c(allowed_choices, collapse=", ")

if(!choice %in% allowed_choices){
  stop(glue::glue("{choice} is not a valid choice.  Please choose from: {concat_choices}"))
}

}

-testing

sample_function(choice = "Test")

Error in sample_function(choice = "Test") : test is not a valid choice. Please choose from: apples, bananas, cherries