How to construct infix operator with usual behavior?
Look at the attributes of Dot
:
Attributes[Dot]
{Flat, OneIdentity, Protected}
The combination of Flat
and OneIdentity
is what takes care of associativity for Dot
, so do the same with CircleDot
:
SetAttributes[CircleDot, {Flat, OneIdentity}];
CircleDot[x_, y_] := x . y
Now, CircleDot
should have the associativity you desire:
z ⊙ y ⊙ x
{124, 170}
Addendum
Addressing the comments.
I think this is the canonical way to create an associative operator.
If you want to create a left-associative or right-associative operator, then you do not want to use the
Flat
attribute. An operator that isFlat
will satisfy:f[x, y, z] === f[f[x, y], z] === f[x, f[y, z]]
which is clearly neither left nor right associative.
Operators like
LeftTee
achieve left-associativity through parsing. For example, the input:Hold[x ⊣ y ⊣ z] //FullForm
Hold[LeftTee[LeftTee[x,y],z]]
does not parse to LeftTee[x, y, z]
. In fact, syntax coloring gives a clue about this:
That is, LeftTee
should only be used as a binary operator. On the other hand, CircleDot
does parse to the Flat
version:
Hold[x ⊙ y ⊙ z] //FullForm
Hold[CircleDot[x,y,z]]
You can include your own associativity rule:
x_⊙y_ := x.y
x_⊙y_⊙z__ := (x⊙y)⊙z
z⊙y⊙x
{124, 170}
Or pick an operator that natively has the desired associativity:
x_ ⊣ y_ := x.y
z ⊣ y ⊣ x
{124, 170}
Recommended reading:
- How can one define an infix operator with an arbitrary unicode character?
- How is + as an infix operator associated with Plus?
- How to make a binary function associative? (Or define an n-ary function?)