How do I get interdependent options?

185 views Asked by At

I want to do something like

foo[OptionsPattern[]] := OptionValue[b]
Options[foo] = {a -> 0, b :> OptionValue[a]};
foo[a -> 1]

and have Mathematica give me 1, instead of 0. Is there a better way to do this than

foo[OptionsPattern[]] := (
  Options[foo] = {a -> 0, b :> OptionValue[a]};
  OptionValue[b]
)
foo[a -> 1]

?

For one thing, it's inefficient to set the options of foo on every call, especially if foo has many options.

2

There are 2 answers

0
Brett Champion On

This is why we have Automatic. I'd use something like:

Options[foo] = {a -> 0, b -> Automatic};

foo[OptionsPattern[]] := 
            Block[{a, b},
               {a, b} = OptionValue[{a, b}];
               If[b === Automatic, a, b]
               ]

foo[]
(* --> 0 *)

foo[a -> 1]
(* --> 1 *)

foo[a -> 1, b -> 2]
(* --> 2 *)

Plus this allows for more complicated interpretation of automatic values if you need it.

0
Mr.Wizard On

You wrote:

I want to do something like

foo[OptionsPattern[]] := OptionValue[b]
Options[foo] = {a -> 0, b :> OptionValue[a]};
foo[a -> 1]

and have Mathematica give me 1, instead of 0.

I get OptionValue[a] as a return for this, not 1 OR 0. This is because OptionValue is to be matched with OptionsPattern[] and it is not. Consider:

ClearAll[foo, a, b]
Options[foo] = {a -> 0};
foo[___] := OptionValue[a]

foo[it, doesnt, matter]
(* Out[]= OptionValue[a] *)

Here is one possible method to effect your goal. I name the OptionsPattern[] so that I can work with these rules outside of OptionValue. Notice that I can still specify an explicit value for b.

ClearAll[foo, a, b]
Options[foo] = {a -> 0, b -> a};
foo[opts : OptionsPattern[]] := OptionValue[b] /. {opts}

foo[a -> 1]
foo[a -> 3, b -> 7]
1
7