Skip to main content
edited tags
Link
Mr.Wizard
  • 273.1k
  • 34
  • 595
  • 1.4k
edited tags
Link
Source Link
vsht
  • 3.6k
  • 14
  • 23

Weird behavior of conditions when using OptionsPattern and OptionValue

I'm trying to define a function that is evaluated differently depending on its options. This code

Options[Foo]={Bar->True};
Foo[a_,b_, OptionsPattern[]]:= A /; OptionValue[Bar];
Foo[a_,b_, OptionsPattern[]]:= B /; !OptionValue[Bar];

works as expected. Evaluating

{Foo[x,y,Bar->True],
Foo[x,y,Bar->False],
SetOptions[Foo,Bar->True];
Foo[x,y,Bar->True],
Foo[x,y,Bar->False],
SetOptions[Foo,Bar->False];
Foo[x,y,{Bar->True}],
Foo[x,y,{Bar->False}],
SetOptions[Foo,Bar->True];
Foo[x,y],
SetOptions[Foo,Bar->False];
Foo[x,y]}

I get

{A, B, A, B, A, B, A, B}

which is precisely what I want. However, if I try to make b a blank sequence, i.e.

Options[Foo]={Bar->True};
Foo[a_,b__, OptionsPattern[]]:= A /; OptionValue[Bar];
Foo[a_,b__, OptionsPattern[]]:= B /; !OptionValue[Bar];

weird things start happening. Evaluating my second code sample I get

{A, B, A, A, A, B, A, B}

which is obviously wrong. A possible workaround is to write

Options[Foo]={Bar->True};
Foo[a_,b__/;FreeQ[{b},Rule], OptionsPattern[]]:= A /; OptionValue[Bar];
Foo[a_,b__/;FreeQ[{b},Rule], OptionsPattern[]]:= B /; !OptionValue[Bar];

However this doesn't seem right to me, since it's actually the job of OptionsPattern to fish out the options from my functions. Of course I could also write

Options[Foo]={Bar->True};
Foo[a_,b__, OptionsPattern[]]:= If[OptionValue[Bar],A,B]

which works as well, but this is still another workaround. Moreover, if I want to have something like (in addition to the regular function definition)

Options[Foo]={Bar->True};
Foo[a_,a_,c___, OptionsPattern[]]:= 0 /; OptionValue[Bar];

then running

{Foo[x,x,Bar->True],
Foo[x,x,Bar->False],
SetOptions[Foo,Bar->True];
Foo[x,x,Bar->True],
Foo[x,x,Bar->False],
SetOptions[Foo,Bar->False];
Foo[x,x,{Bar->True}],
Foo[x,x,{Bar->False}],
SetOptions[Foo,Bar->True];
Foo[x,x],
SetOptions[Foo,Bar->False];
Foo[x,x]}

again produces wrong results

{0, Foo[x, x, Bar -> False], 0, 0, 0, Foo[x, x, {Bar -> False}], 0, 
 Foo[x, x]}

and my only solution is to use

Options[Foo]={Bar->True};
Foo[a_,a_,c___/;FreeQ[{c},Rule], OptionsPattern[]]:= 0 /; OptionValue[Bar];

which is kind of a hack.

So my question is, why using conditions with OptionValue and OptionsPattern works if the last pattern before OptionsPattern is a blank, but fails if it is a blank sequence. Is it a bug, or am I missing something essential about OptionsPattern?

I'm observing this behavior both on Mathematca 9.0.1 and Mathematica 10.0.1 under Linux.