4

I'm new to R functions and so far i would check arguments like:

foo = function(state = c("solid", "liquid"),
               thing = c("rock", "water")) {
  
  state = match.arg(state)
  thing = match.arg(thing)
  
  if (state == "solid" & thing == "water") {
    stop("thing can't be water if state is solid!")
  }
  
  if (state == "liquid" & thing == "rock") {
    stop("thing can't be rock if state is liquid!")
  }
  
}

foo("solid", "brick")
#> Error in match.arg(thing): 'arg' deve ser um dentre "rock", "water"

foo("solid", "water")
#> Error in foo("solid", "water"): thing can't be water if state is solid!

foo("liquid", "rock")
#> Error in foo("liquid", "rock"): thing can't be rock if state is liquid!

Created on 2020-06-28 by the reprex package (v0.3.0)

But it seems a lot of work when working with several args.

I had a look at assetthat and checkmate packages but it wasn't clear to me what is the correct or standard way to do it.

Alberson Miranda
  • 1,248
  • 7
  • 25

1 Answers1

4

I suggest either an allowlist or denylist, depending on whichever would be shorter (how many exceptions you'll have), but you'll have to hard-code them somehow.

For instance:

foo = function(state = c("solid", "liquid", "both"),
               thing = c("rock", "brick", "water", "either")) {
  
  state = match.arg(state)
  thing = match.arg(thing)

  state_denylist <- list(
    solid = "water",
    liquid = c("rock", "brick")
  )

  if (thing %in% state_denylist[[state]]) {
    stop("thing cannot be ", sQuote(thing), " if state is ", sQuote(state))
  }
 
}

Alternatively, if it's easier to define the allowed combinations, then perhaps state_allowlist and change your logic accordingly (... && ! thing %in% ...).

r2evans
  • 141,215
  • 6
  • 77
  • 149
  • AlbersonMiranda, I simplified it *slightly*, since if `state` is not in the deny list, then `%in% state_denylist[[state]]` is effectively `%in% NULL` which is always (and safely) `FALSE`. The previous version is a little more declarative but perhaps mostly style. Your choice. – r2evans Jun 28 '20 at 17:55