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?

  • 1
    $\begingroup$ This is how I usually do it except for the minor difference of writing it as Options[g] = Options[f]; SetOptions[g, {optA -> 0, optB -> 0}] (instead of filtering). The most annoying thing for me about this solution is that if I later SetOptions on f, the change won't be inherited by g. But this is what happens with builtins too (e.g. Plot vs Graphics) and the workaround is rather verbose and complicated. $\endgroup$ – Szabolcs Nov 12 '14 at 19:37
  • $\begingroup$ @Szabolcs: So the explicit OptA -> OptionValue[OptA], optB -> OptionValue[optB] in the call to f is indeed necessary? $\endgroup$ – orome Nov 12 '14 at 20:06
  • 1
    $\begingroup$ Related: (20470) $\endgroup$ – Mr.Wizard Jan 10 at 3:39
  • $\begingroup$ @Mr.Wizard I must've forgotten about that discussion when posting my answer here. I have added a link to it to my answer. $\endgroup$ – Leonid Shifrin Jan 10 at 4:22
  • $\begingroup$ @Leonid Surely I have forgotten more, but thank you. :-) $\endgroup$ – Mr.Wizard Jan 10 at 19:40

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.



(* {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.

| improve this answer | |
  • 1
    $\begingroup$ This is a great solution, but I can't get it to work for me in practice. I get errors deep in my code about some options not being valid. I'll see if I can generate an M(N)WE. $\endgroup$ – orome Nov 13 '14 at 18:37
  • $\begingroup$ I was at a loss for how to do exactly this, your answer helped me a lot! $\endgroup$ – gpap Jan 13 at 9:13
  • $\begingroup$ @gpap Thanks! I am glad this was helpful. This is one of the things that are not very easy to infer from the docs, although all bits and pieces are there. $\endgroup$ – Leonid Shifrin Jan 13 at 12:09

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:

Options[f] = {optA -> 1, optB -> 1, optC -> 1};
f[x_, opts : OptionsPattern[]] := OptionValue[{optA, optB, optC}]

We can define g in following way:

(* 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

(* {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];
(* {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];
(* {0, 0, 0} *)
(* {1, 1, 2} *)

You can also, at any time, decide to use inherited option value:

SetOptions[g, optA :> OptionValue[f, optA]];
(* {1, 0, 0} *)
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.