Function default arguments and named values

FunctionR

Function Problem Overview


Let's say I have an R function in which the arguments can be a one of a few predefined named values (one of which is the default) or a custom character vector. How should I implement this without relying on magic value names or another flag?

#allow use of predefined subsets or pass their own list
bratPack<-function(members='CORE',...){
  if (members=='CORE')
    members<-c('Emilio Estevez','Anthony Michael Hall','Rob Lowe','Andrew McCarthy','Demi Moore','Judd Nelson','Molly Ringwald','Ally Sheedy')
  else if (members=='ALL')
    members<-c('Emilio Estevez','Anthony Michael Hall','Rob Lowe','Andrew McCarthy','Demi Moore','Judd Nelson','Molly Ringwald','Ally Sheedy','James Spader','Robert Downey, Jr.','Jon Cryer', 'John Cusack', 'Kevin Bacon', 'Jami Gertz', 'Mary Stuart Masterson', 'Matthew Broderick', 'Sean Penn', 'Kiefer Sutherland')
  ...
}

Function Solutions


Solution 1 - Function

From your example we have the choice of "CORE" and "ALL". If those are the two options, then we specify them in the function definition for the argument 'members'. E.g.:

foo <- function(x, members = c("CORE", "ALL")) {
    ## do something
}

That function definition sets up the allowed values for argument 'members', with a default of "CORE" as this is the first named option.

The code that one uses within the function body is match.arg(), as @Joris has already mentioned, but because we have set the function up as above, we can simply the usage to just match.arg(members).

So we can write foo as:

foo <- function(x, members = c("CORE", "ALL")) {
    ## evaluate choices
    members <- match.arg(members)
    ## do something
    print(members)
}

Which we use like this:

> foo()
[1] "CORE"
> foo(members = "CORE")
[1] "CORE"
> foo(members = "ALL")
[1] "ALL"
> foo(members = "3rdRate")
Error in match.arg(members) : 'arg' should be one of “CORE”, “ALL”

Notice the behaviour when we supply an string not included in the set of options. We get an intuitive error message, all because we set up the options in the function arguments.

Solution 2 - Function

I'd use some constant dataframe somewhere in the package:

.mdata <- data.frame(
    CORE= c(TRUE,FALSE,TRUE),
    OLD = c(TRUE,TRUE,FALSE),
    ALL = c(TRUE,TRUE,TRUE),
    row.names=c("John Doe", "Jan Janssen", "Piet Peters")
)

bratPack<-function(members='CORE',...){
  m.tmp <- try(
         match.arg(members,names(.mdata),several.ok=T),
         silent=T) 

  if(!is(m.tmp,"try-error"))
    members <- rownames(.mdata)[.mdata[[members]]]

  print(members)
}

> bratPack('CORE')
[1] "John Doe"    "Piet Peters"

> bratPack('Jan Janssen')
[1] "Jan Janssen"

> bratPack(c("John Doe","Dick Dickers"))
[1] "John Doe"     "Dick Dickers"

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJeremy LeipzigView Question on Stackoverflow
Solution 1 - FunctionGavin SimpsonView Answer on Stackoverflow
Solution 2 - FunctionJoris MeysView Answer on Stackoverflow