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