1
$\begingroup$

I have read this post: How to avoid collision between optional arguments and options, and use Mr.Wizard's method to solve this problem. But when I add conditions to optional arguments, it seems that conditions have been repeatedly judged.

f[x_, Shortest[y_ : 1, 1], Shortest[z_ : 11, 2], 
    OptionsPattern[{"g" -> Identity, "h" -> (#^2 &)}]] /; 
   If[MemberQ[{1, 2, 3}, y], 
    If[MemberQ[{11, 12, 13}, z], True, Print[Style[{x, y, z}, Red]]; 
     False], Print[Style[{x, y, z}, Red]]; False] := 
  OptionValue["h"][OptionValue["g"][x + y + z]];
In[1]:= f[0]
Out[1]= 144

In[2]:= f[0, 1]
Out[2]= 144

In[3]:= f[0, 4]
{0, 4, 11}
{0, 1, 4}
Out[3]= f[0, 4]

In[4]:= f[0, 1, 11]
Out[4]= 144

In[5]:= f[0, 1, 14]
{0, 1, 14}
Out[5]= f[0, 1, 14]

In[6]:= f[1, "g" -> Sqrt]
Out[6]= 13

In[7]:= f[0, 13]
{0, 13, 11}
Out[7]= 196

If conditions are judged inside function, it works normally (I'm not sure).

f[x_, Shortest[y_ : 1, 1], Shortest[z_ : 11, 2], 
   OptionsPattern[{"g" -> Identity, "h" -> (#^2 &)}]] := 
  If[MemberQ[{1, 2, 3}, y], 
   If[MemberQ[{11, 12, 13}, z], 
    OptionValue["h"][OptionValue["g"][x + y + z]], 
    Print[Style[{x, y, z}, Red]]; False], 
   Print[Style[{x, y, z}, Red]]; False];
In[1]:= f[0]
Out[1]= 144

In[2]:= f[0, 1]
Out[2]= 144

In[3]:= f[0, 4]
{0, 4, 11}
Out[3]= False

In[4]:= f[0, 1, 11]
Out[4]= 144

In[5]:= f[0, 1, 14]
{0, 1, 14}
Out[5]= False

In[6]:= f[1, "g" -> Sqrt]
Out[6]= 13

In[7]:= f[0, 13]
{0, 13, 11}
Out[7]= False

My goal is to get the optional arguments in order, if conditions are not met, return the unevaluated expression like built-in functions and print error message only once.

In[1]:= f[0, 4]
error message
Out[1]= f[0, 4]

In[2]:= f[0, 4, 11]
error message
Out[2]= f[0, 4, 11]

In[3]:= f[0, 4, 14]
error message
Out[3]= f[0, 4, 14]

In[4]:= f[0, 4, "g" -> Sqrt]
error message
Out[4]= f[0, 4, "g" -> Sqrt]
```
$\endgroup$

1 Answer 1

2
$\begingroup$

My goal is to get the optional arguments in order, if conditions are not met, return the unevaluated expression like built-in functions and print error message only once.

The trick with Shortest seems fragile to me, and can easily be avoided in this case by writing better patterns for the y and z variables

f[x_, y : 1 | 2 | 3 : 1, z : 11 | 12 | 13 : 11,
    OptionsPattern[{"g"->Identity, "h"->(#1^2&)}]] := OptionValue["h"][OptionValue["g"][x + y + z]];
f[args__] := (
    Print["message for bad arguments ", {args}];
    Null /; False
)

I believe this passes all the requirements.

$\endgroup$

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.