# Optional throws error when called from a package. Workaround?

Bug introduced in 8.0 or earlier and fixed in 11.0.0

Case number: 305932.

In the front-end notebook (Mathematica 9.0 and 10.2):

g[x: Optional[_,default]]:=x;


has no problems, and works correctly (g[] outputs default, and g[1] outputs 1).

However, when the following package is constructed in an .m file called Dummy.m:

BeginPackage["Dummy"];
f
g; Thing;

Begin["Private"];
g[x: Optional[_,default]]:=x; (*Minimal case causing problem*)

f[x: Optional[Thing->{_},Thing->{1}]]:=x;  (*I need this in my package*)
End[];
EndPackage[];


The same line of code throws a General::patop error upon package initialization. (The definition for f is the structure of the optional argument I need to achieve in my package.)

<<Dummy


Is this a bug? and I can I define f in my package?

• Ok, I may have found the workaround: Put the pattern name x inside the Optional like so: g[Optional[x: _,default]]. However, the fact that the former syntax doesn't throw an error in the front-end but does when called from within a package seems a bit strange... Dec 30 '15 at 18:07
• : is actually shorthand notation for Optional. This means x:Optiona[...] is Optional[x,Optional[_,default]]. The way to specify this is with f[x_:default]:=x Dec 30 '15 at 20:04
• Really? According to reference.wolfram.com/language/ref/Pattern.html, : denotes pattern name... Dec 30 '15 at 20:07
• Check out Optional. I'm not sure why there are two usages for the same symbol that seem only to depend on context. Dec 30 '15 at 20:24
• Oh dear... this is what I would call a catastrophic design flaw. Thanks. Dec 30 '15 at 22:16

String "x : Optional[_, default]" in StandardForm is interpreted as:

ToExpression["x : Optional[_,default]", StandardForm, HoldComplete] // FullForm
(* HoldComplete[Optional[Pattern[x, Blank[]], default]] *)


and in InputForm as:

ToExpression["x : Optional[_,default]", InputForm, HoldComplete] // FullForm
(* HoldComplete[Pattern[x, Optional[Blank[], default]]] *)


The latter is done when reading a package file, and similar thing to the former is done in the front-end.

As per comment of Itai Seggev in the front-end x : Optional[_,default] is represented by following boxes, which are interpreted as following expression:

RowBox[{"x", ":", RowBox[{"Optional", "[", RowBox[{"_", ",", "default"}], "]"}]}] // MakeExpression // FullForm
(* HoldComplete[Optional[Pattern[x, Blank[]], default]] *)


instead of HoldComplete[Pattern[x, Optional[Blank[], default]]], which is the surprising (possibly buggy) fact.

I think it should be reported to WRI.

As can be seen in Details section of Optional documentation, what you called a workaround, in a comment, is actually the correct, documented way, which in full form is:

Optional[Pattern[name, something], defaultValue]


In a package you can use full form directly:

Optional[Pattern[x, Thing->{_}], Thing->{1}]


use infix form of Pattern:

Optional[x : (Thing->{_}), Thing->{1}]


or infix form of both Pattern and Optional:

x : (Thing->{_}) : (Thing->{1})

• I agree that the StandardForm ToExpression output seems wrong. I couldn't find an existing bug report about this, although it's likely to be an old bug. I've opened the bug report. Any licensed user who is interested in being notified when this bug is resolved can ask Tech Support to attach their contact information to bug 305932. Dec 31 '15 at 0:44
• Just one point of clarification: while it is true that the FE by default uses the StandardForm/TraditionalForm parser MakeExpression, which is different from the InputForm parser used by package files and a standalone kernel, the FE doesn't actually make the ToExpression call seen above. The FE maintains "box expressions" which you can see using the Cell -> Show Expression menu item. These are sent directly when the head Optional appears to the right of a colon, MakeExpression is parsing the result incorrectly. An old bug, but probably one which should be pretty easy to fix. Dec 31 '15 at 18:02

I rewrote your package like this

BeginPackage["Dummy"]

Clear[f,g,Thing]

Begin["Private"]
g[x_:default]:=x
f[x:(Thing->{_}):(Thing->{1})]:=x
End[]

EndPackage[]


and saved it to /Users/oldmg/Desktop/Dummy.m and ran the following code

Quiet @ Remove["Dummy*"]
<< "/Users/oldmg/Desktop/Dummy.m"  (*  *)

dummy = 42;
g[] && g[2]


DummyPrivatedefault && 2

f[] && f[Thing -> {42}] && f[42]


(Thing -> {1}) && (Thing -> {42}) && f[42]

I believe this is the behavior you are looking for in Dummy.m, so you might use this as a guide when you are writing your non-toy package code.