Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 42 additions & 32 deletions mathics/builtin/patterns/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,48 +19,58 @@


class Optional(InfixOperator, PatternObject):
"""

<url>:WMA link:https://reference.wolfram.com/language/ref/Optional.html</url>
"""<url>:WMA link:https://reference.wolfram.com/language/ref/Optional.html</url>

<dl>
<dt>'Optional'[$pattern$, $default$]
<dt>'$pattern$ : $default$'
<dd>is a pattern which matches $pattern$, which if omitted
should be replaced by $default$.
<dd>is a pattern matching $pattern$; when $pattern$ is omitted, \
$default$ is substituted for $pattern$.
</dl>

Optional is used to specify optional arguments in function signatures.

Set up a default value of 1 for the pattern 'y_' in function 'f':

>> f[x_, y_:1] := {x, y}
>> f[1, 2]
= {1, 2}

When we specify a value for the 'y' parameter, it has the value provided:
>> f[a, 2]
= {a, 2}

But if the 'y' parameter is missing, we replace the parameter \
using the default given in the delayed assignment above:

>> f[a]
= {a, 1}

Note that '$symb$ : $pattern$' represents a 'Pattern' object. However, there is no \
disambiguity, since $symb$ has to be a symbol in this case.

>> x:_ // FullForm
= Pattern[x, Blank[]]
>> _:d // FullForm
= Optional[Blank[], d]
>> x:_+y_:d // FullForm

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example does not seem motivated.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the motivation is to show the order of interpretation: the second colon is interpreted first, to build the inner Optional expression, and then the first one is interpreted as a named Pattern.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I'll add this example back, adding this explanation.

@rocky rocky Jan 20, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the motivation is to show the order of interpretation: the second colon is interpreted first, to build the inner Optional expression, and then the first one is interpreted as a named Pattern.

Hmm... It looks like we may have the wrong Precedence indicated for Pattern. We give Pattern value 670 while it is 150 in WMA. In both WMA and Mathics3, though, Optional is 140. So the behavior is natural.in WMA while in Mathics3, it goes contrary to what is specified.

Is this something we specifically hacked around? and would get wrong were we to follow the usual precedence rules?

Edit what we have would give the same behavior. But, I wonder if there is a reason not to use the same value 150.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at the precedence issue, and it is tagged with the right value in mathics_scanner, but Pattern is not tagged as an operator in mathics-core, and if that's changed, other things break. 670 is the magic number that's given when we can't find a precedence value tagged.

Sigh.

= Pattern[x, Plus[Blank[], Optional[Pattern[y, Blank[]], d]]]

's_.' is equivalent to 'Optional[s_]' and represents an optional parameter which, if omitted, \
gets its value from 'Default'.
>> FullForm[s_.]
= Optional[Pattern[s, Blank[]]]

'InputForm' shows it in its 'Infix' or 'Postfix' form depending on the \
number of parameters:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InputForm, by default, uses infix for equations. I do not understand from the example where the number of parameters is coming into play. And I do not see where postifx notation is selected.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no Infix form with just one argument...

@rocky rocky Jan 20, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, this degenerate case is defined on Infix:

In[2]:= Infix[{1}, "+"]
Out[2]= 1

But the larger and more important point is: what does this Infix and Postfix stuff have to do with the examples?

>> InputForm[s_:a+b^2]
= s_ : a + b^2
Following WMA conventions,
>> InputForm[Optional[s__]]
= (s__.)
>> Default[h, k_] := k
>> h[a] /. h[x_, y_.] -> {x, y}
= {a, 2}
Do not confuse with '$symbol$ : $pattern$', which is also a 'Pattern'. \
The distinction is to left of the colon. When a $symbol$ is given, we get:

>> y:1 // FullForm
= Pattern[y, 1]

Whereas, in an 'Optional' expression, on the left of the colon we have a pattern like 'y_':

>> y_:1 // FullForm
= Optional[Pattern[y, Blank[]], 1]

The special form 'y_.' is equivalent to 'Optional[y_]':

>> FullForm[y_.]
= Optional[Pattern[y, Blank[]]]

In this situation, when the is 'y' parameter omitted, the value comes from <url>\
:Default:/doc/reference-of-built-in-symbols/options-management/default/</url>:

>> Default[g] = 4
= 4

>> g[x_, y_.] := {x, y}

>> g[a]
= {a, 4}

"""

arg_counts = [1, 2]
Expand Down
Loading