How do I override options with my own defaults?
Here is what I do in such cases ([edit from 01/10/2020 - apparently, this technique has been exposed on this site earlier, at least partially, in this nice answer by Mr.Wizard - which I definitely read but must have forgotten at the time of posting my answer]) :
ClearAll[g, f];
Options[f] = {optA -> 1, optB -> 1, optC -> 1};
f[x_, opts : OptionsPattern[]] :=
{OptionValue[optA], OptionValue[optB], OptionValue[optC]}
Options[g] = {optA -> 0, optB -> 0};
g[x_, opts : OptionsPattern[{g, f}]] := f[x, opts, Sequence @@ Options[g]]
In other words, only define options for g
which belong to g
, and inherit other options from f
via the argument of OptionsPattern
. Also, pass all options of g
explicitly in the call to f
, as in Sequence @@ Options[g]
. The fact that they come after opts
means that they will be over-ridden by opts
, as they should be.
Examples:
g[1]
(* {0, 0, 1} *)
g[1, optA -> 2]
(* {2, 0, 1} *)
The added advantage of this scheme is that it is free from the flaw mentioned by Szabolcs, in that subsequent changes of Options[f]
will be picked up in this method automatically.
Trick that I sometimes find useful is "inheriting" of default option value from another symbol using delayed rule like:
optName :> OptionValue[anotherSymbol, optName]
With f
defined as:
ClearAll[f];
Options[f] = {optA -> 1, optB -> 1, optC -> 1};
f[x_, opts : OptionsPattern[]] := OptionValue[{optA, optB, optC}]
We can define g
in following way:
ClearAll[g];
(* Inherit all options from f *)
Options[g] = # :> OptionValue[f, #] & @@@ Options[f];
(* Change default values of some of them. *)
SetOptions[g, optA -> 0, optB -> 0];
g[x_, opts : OptionsPattern[]] := f[x, opts, Options[g]]
Basically it works as previous solutions
g[x]
(* {0, 0, 1} *)
g[x, optA -> 2, optC -> 2]
(* {2, 0, 2} *)
g
inherits options from f
in all situations, not only in above specific function call.
OptionValue[g, {optA, optB, optC}]
(* {0, 0, 1} *)
If you change default options of f
, then non-overridden default options of g
will inherit this change in all circumstances:
SetOptions[f, optC -> 2];
g[x]
(* {0, 0, 2} *)
OptionValue[g, {optA, optB, optC}]
(* {0, 0, 2} *)
Also at any time you can decide to change default value of any option (not only those overridden when g was defined) only on g
without affecting f
.
SetOptions[g, optC -> 0];
g[x]
(* {0, 0, 0} *)
f[x]
(* {1, 1, 2} *)
You can also, at any time, decide to use inherited option value:
SetOptions[g, optA :> OptionValue[f, optA]];
g[x]
(* {1, 0, 0} *)