Mathematica: Checking your function for wrong options
Mathematica has a unique way of reporting wrong options. That is if you call a built-in function with an option that does not belong to this function, you see an error message of the following form and Mathematica returns your expression unevaluated:
We have to solve these problems:
- How can we identify wrong options
- How can we create a message that contains our original call
- How can we return unevaluated
1. Checking for wrong options
When we have a list of options, we can employ FilterRules
to extract valid ones. Remember that FilterRules
works
on rules. Therefore, it is not restricted to Options
and can be used in other situations as well.
Consider the following simple example with a not yet defined function f
The second argument of FilterRules
is a pattern and, therefore, we can easily turn the selection around by using Except
You surely see that this is already the solution to this problem. If there is no invalid option in the list, the output will be the empty list and the user has not given any wrong option.
2. Creating a message that contains the wrong option and the original call
First, let us attach the error message to the symbol f
that we will need for this. The two backtick pairs are the
placeholder where we will inject the values later.
As Michael has pointed out, this is not strictly necessary.
The message General::optx
already exists and if you don’t define it for your function, calling Message[f::optx]
will define the messages for your symbol f
and do the right thing.
Next, we will define a checkOpts
function that tests the options and prints the message if there were any invalid options
in the call. As we saw, we need both the options that were provided by the user and the original options of the function
Since we also need the original call to print it, checkOpts
will get your complete call as its argument and will extract
all required things by itself.
Since your original call would be evaluated when we do checkOpts[f[args, opts]]
, we need to give checkOpts
the attribute
HoldFirst
. This is one property of how Mathematica evaluates code: Arguments to a function are evaluated before the
function is called. Therefore, we need to suppress this.
The body of the function does nothing magical. It extracts that bad rules as discussed above and if there are any bad
rules, it prints the message and returns False
. Otherwise, it will return True
. The interesting part is that we assign
the complete function call with call :
and that we use a generic func_
that can be any function, not only our f
we
are currently working on.
We can test this function even without having f
properly defined yet
checkOpts[f[x, y, z, {optA -> 3}]]
(* True *)
checkOpts[f[x, y, z, {optA -> 3, wrongOpt -> Automatic}]]
(*
During evaluation of In[14]:= f::optx: Unknown option wrongOpt->Automatic
in f[x,y,z,{optA->3,wrongOpt->Automatic}].
False
*)
3. How can use this in a definition, and we return unevaluated?
To use this, we test the whole call pattern of your function. That means we include a PatternTest
like this
f[x_, OptionsPattern[]]?checkOpts := x^2 + OptionValue[optB]
Let’s test it. The default option value for optB
is 1:
f[10]
(* 101 *)
Providing a custom option value for it
f[x, optB -> 10]
(* 10 + x^2 *)
and finally, giving something invalid
I promised that checkOpts
is generic enough to use it in any other function as well. Note that now, I don’t define the message
for combine
and let Mathematica figure it out. Let us try this
Options[combine] := { function -> Plus };
combine[x_, y_, OptionsPattern[]]?checkOpts := OptionValue[function][x, y];
combine[20, 30]
(* 50 *)
combine[20, 30, function -> Times]
(* 600 *)
combine[20, 30, Frame -> True]
(*
During evaluation of In[34]:= combine::optx: Unknown option
Frame->True in combine[20,30,Frame->True].
Out[34]= combine[20, 30, Frame -> True]
*)