With settings
it is possible to create an options manager that extensively checks or manipulates the option values passed by a user. There are two use cases for this. First it allows you to create a useful error or warning when a user passes an option value that is incorrect. Second, it allows you to preprocess the option values before storing them. For example by casting a string to lower case.
Suppose we want an option called foo
, that can take three values: boo
, bar
and baz
. We want to create an options manager that first casts the user value to lower case. Next, if the value is valid, the lower-case variant will be stored, otherwise an informative error is thrown.
To do this, first write a function that performs these checks. Make sure that the function returns the value that needs to be stored.
foo_check <- function(x){
allowed <- c("boo","bar","baz")
# cast to lowercase
x <- base::tolower(x)
if ( !x %in% allowed ){
stop("Option foo must be in 'boo', 'bar', or 'baz'", call. = FALSE)
} else {
x
}
}
Next, define the options manager as follows.
my_options <- options_manager(foo="boo", .allowed = list( foo = foo_check) )
my_options("foo")
#> [1] "boo"
It is important that the names in the .allowed
list agree with the names of the options.
Let’s see what happens when we set the option with capitals:
Observe that the stored option is in lowercase whereas the user-defined value includes upper-case letters.
The function that you write for checking and/or manipulating option values has to satisfy certain rules to make it work. It is obligated for the function to
It is advised to make the cheking function throw an error (stop) when a user passes an invalid value.
In the above example, we have created a function where we hard-wired the possible values in the function code. Suppose you have two variables where you want to perform the same check, but with different values. In this example we show how to add this flexibility.
We use the fact that in R, a function is a variable, just like any other R object. In particular this means that in R, a function can return other functions as output. We will use this to make a function called make_checker
that creates a customized checker function for us. The input of this function are the allowed values.
make_checker <- function(allowed){
.allowed <- allowed
function(x){
x <- tolower(x)
if (!x %in% .allowed){
stop(sprintf("Allowed values are %s",paste0(.allowed, collapse=", ")), call.=FALSE)
} else {
x
}
}
}
We now create an options manager with two options: foo
, with valid values hey
and ho
and bar
, with valid values fee
, fi
, fo
, fum
.
my_new_options <- options_manager(foo = "hey", bar="fee"
, .allowed = list(
foo = make_checker( c("hey", "ho") )
, bar = make_checker( c("fee", "fi", "fo", "fum") )
))
Let’s try it out:
Here are some exercises to aquint yourself with this functionality.
boo
, with default value 1, where the allowed values are integer powers of two \((1, 2, 4,\ldots)\). If the user supplies a value that is not a power of two, an error is thrown.