Search code examples
rparameter-passing

Vectorized parameter validation in R?


I'm trying to vectorize parameter function validation by adapting an example I saw elsewhere. Right now, this returns 0 for everything. Using browser() function I can step into the apply function and I see that instead of looking for the parameter name (i.e. P1) to determine the allowed values, it's looking for the parameter name "M" (i.e., the parameter value). I believe I need to someone assigned the passed parameter values to each parameter name, but I'm not sure how to do this. Or, if I'm completely off base, is there a better way to do this? The obvious solution is to just check each parameter individually by repeating the code, but that seems sloppy/ineffiicent, and I was hoping to learn a better way.

Any help would be GREATLY appreciated. Thanks!

myFunc <- function(P1 = c("F", "M"), 
                          P2 = c("HighSchool_GPA", "SAT"), 
                          P3 = 2007:2012, 
                          P4 = c("Yes", "No")
                          ) {
  browser()
  # Validate parameter values
  allowed_values <- list(P1 = c("F", "M"), 
                         P2 = c("HighSchool_GPA", "SAT"), 
                         P3 = 2007:2012, 
                         P4 = c("Yes", "No"))

  # Attempt to validate all values at once
  valid_indexes <- sapply(
    c(P1, P2, P3, P4), 
    function(param) {
      allowed <- allowed_values[[names(param)]] 
      match(param, allowed, nomatch = 0)
      }
    )
  
  if (any(valid_indexes == 0)) {
    stop("Invalid parameter value(s). 
         Please check values passed. Use only allowed values.")
  }
}

example <- myFunc("M", "HighSchool_GPA", 2010, "No")

Solution

  • For this specific example, where the possible values of arguments are specified in the function definition, match.arg looks like an obvious solution. This page has some explanation.

    In your example this would translate to something like:

    myFunc <- function(P1 = c("F", "M"), 
                       P2 = c("HighSchool_GPA", "SAT"), 
                       P3 = 2007:2012, 
                       P4 = c("Yes", "No")
    ) {
    
      P1 <- match.arg(P1)
      P2 <- match.arg(P2)
      stopifnot(P3 %in% 2007:2012) # match.arg only works with character vectors
      P4 <- match.arg(P4)
     
    }
    
    example <- myFunc("F", "HighSchool_GPA", 2010, "No")