I'm calling a function f
from within a function g
and would like to pass any valid options for f
to g
, replacing some (say, optA
and optB
) with defaults different from those defined for f
.
What is the right way to do this?
I can get things to (seemingly) work with
Options[g] = Join[FilterRules[Options[f], Except[optA | optB]], {optA -> 0, optB -> 0}];
g[x, opts : OptionsPattern[]] :=
f[x, opts, OptA -> OptionValue[OptA], optB -> OptionValue[optB]]
but this looks pretty verbose to me. Is there a better, more idiomatic, way?
Answer
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.
Comments
Post a Comment