How do you explicitly state the valid settings for an option? Take this example for instance
Options[myFunc] = {opt1 -> "SomeString"};
myFunc[OptionsPattern[]] := Print[OptionValue[opt1]];
myFunc prints the value of the option. If we evaluate myFunc[opt1 -> {1, 2}] then it prints {1, 2}. This function will essentially print anything that you set to opt1. My question is, how can I make sure that my function only accept a given number of values for opt1. We can start with something simple like a String and an Integer.
To have a better idea of the behavior that we would expect when given the wrong values for opt1 we can take a look at what happens when we give the wrong values for PlotRange in the function Plot.

In the example given in the picture I purposely gave wrong values to the PlotRange options and gave me a message specifying the correct type of values for that particular options. It seems that it PlotRange ended up taking its default value and thus it return the Graphics object.
In the simple example what we would like to obtain is something like:
myFunc::sometag : Value of option opt1 -> `1` is not a string or integer.
How to achieve this?
A straightforward solution
Here is a simple way:
For example:
Making it general with custom assignment operators
We can use the fact that
OptionValueinside a function works with a single argument being an option name, to factor out the error-checking tedium. This is possible by using mma meta-programming facilities. Here is the code for a custom assignment operator:What it does is to take a function definition as a rule
f_[args___]:>body_, and alsothe specifications for the acceptable options settings and actions to perform upon detection of an error in one of the passed options. We then inject the error-testing code (
Scan) before the body gets executed. As soon as the first option with inappropriate setting is found, error flag is set toTrue, and whatever code is specified in theFail:>code_part of specifications for that option. The option specification pattern(_ -> {_, Fail :> _})should read(optname_ -> {optpattern_, Fail :> onerror_}), whereoptnameis an option name,optpatternis a pattern that the option value must match, andonerroris arbitrary code to execute if error is detected. Note that we useRuleDelayedinFail:>onerror_, to prevent premature evaluation of that code. Note b.t.w. that theOptionSpecswrapper was added solely for readability – it is a completely idle symbol with no rules attached to it.Here is an example of a function defined with this custom assignment operator:
Here are examples of use:
Adding option checks to already defined functions automatically
You might also be interested in a package I wrote to test the passed options:
CheckOptions, available here. The package comes with a notebook illustrating its use. It parses the definitions of your function and creates additional definitions to check the options. The current downside (apart from generation of new definitions which may not always be appropriate) is that it only covers older way to define options throughOptionQpredicate (I did not yet update it to coverOptionValue - OptionsPattern. I will reproduce here a part of the accompanying notebook to illustrate how it works:Consider a model function:
Suppose we want to return an error message when an option
FontSizeis passed to our function:We add the option – checking definitions:
As you can see, once we call
AddOptionsCheck, it generates new definitions. It takes the function name, the testing function, and the function to execute on failure. The testing function accepts the main function name, options passed to it (wrapped inHold), and non-options arguments passed to it (also wrapped inHold). From the generated definitions you can see what is does.We now check on various inputs:
Please note that the test function can test for arbitrary condition involving function name, passed arguments and passed options. There is another package of mine,
PackageOptionChecks, available at the same page, which has a simpler syntax to test specifically r.h.s. of options, and can also be applied to entire package. A practical example of its use is yet another package,PackageSymbolsDependencies, whose functions’ options are “protected” byPackageOptionChecks. Also,PackageOptionChecksmay be applied to functions inGlobal'context as well, it is not necessary to have a package.One other limitation of the current implementation is that we can not return the function unevaluated. Please see a more detailed discussion in the notebook accompanying the package. If there is enough interest in this, I will consider updating the package to remove some of the limitations I mentioned.