What the documentation means is that for a symbol f
with attribute OneIdentity
, pattern forms like f[_.,x]
, f[_.,f[_.,x]]
, etc. (Note the Possible Issues section!) will not only match expression like f[4,a]
but also an expression without a Head f
.
Take the CirclePlus
, which has no built-in meaning or any attribute, as an example.
Clear[CirclePlus]
ClearAttributes[CirclePlus, Attributes@CirclePlus];
DefaultValues[CirclePlus] = {};
Attributes[CirclePlus]
{}
This will work as expected:
k⊕y /. a_⊕x_ :> {a, x}
k⊕y /. a_.⊕x_ :> {a, x}
{k, y}
{k, y}
But this won't work because a_.⊕x_
or (a_:1)⊕x_
won't match y
:
y /. a_.⊕x_ :> {a, x}
y /. (a_: 1)⊕x_ :> {a, x}
y
y
Instead of introducing a special rule like x_:>{1,x}
, we can add the OneIdentity
to CirclePlus
:
SetAttributes[CirclePlus, OneIdentity]
Now this works as well:
y /. (a_: 1)⊕x_ /; (Echo[a]; True) :> {a, x}
1
{1, y}
This still won't work
y /. a_.⊕x_ :> {a, x}
until CirclePlus
gets DefaultValues
:
Default[CirclePlus] := RandomReal[];
Now a_.⊕x_
will match y
:
y /. a_.⊕x_ /; (Echo[a]; True) :> {a, x}
0.217426
{0.217426, y}
And nested CirclePlus
will also match y
:
y /. a_.⊕(b_.⊕x_) /; (Echo[{a, b}]; True) :> {a, b, x}
{0.934169, 0.157904}
{0.934169, 0.157904, y}
y /. a_.⊕(x_⊕b_.) /; (Echo[{a, b}]; True) :> {a, b, x}
{0.319821, 0.490549}
{0.319821, 0.490549, y}
or match 4⊕y
:
4⊕y /. a_.⊕(x_⊕b_.) /; (Echo[{a, b}]; True) :> {a, b, x}
{4, 0.861579}
{4, 0.861579, y}