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.

  1. I think this is the canonical way to create an associative operator.

  2. 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 is Flat will satisfy:

    f[x, y, z] === f[f[x, y], z] === f[x, f[y, z]]
    

which is clearly neither left nor right associative.

  1. 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:

enter image description here

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?)