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.
Options[Foo] = {Bar -> True}; Foo[a_, b___, c_ /; ! OptionQ[c], OptionsPattern[]] := A /; OptionValue[Bar]; Foo[a_, b___, c_ /; ! OptionQ[c], OptionsPattern[]] := B /; ! OptionValue[Bar];
$\endgroup$