1

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] ```

李子涵
  • 326
  • 1
  • 3

1 Answers1

2

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.

Jason B.
  • 68,381
  • 3
  • 139
  • 286