Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get interdependent options?

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.

like image 413
Jason Gross Avatar asked Oct 28 '11 01:10

Jason Gross


2 Answers

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.

like image 105
Brett Champion Avatar answered Nov 01 '22 03:11

Brett Champion


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
like image 33
Mr.Wizard Avatar answered Nov 01 '22 03:11

Mr.Wizard