# How to make a binary function associative? (Or define an n-ary function?)

Suppose I have a simple function that I assign to an operator

f[a_, b_] := a + b
CirclePlus = f


Then I want to write

1 (+) 2 (+) 3


But it doesn't work, because it's trying to evaluate f[1,2,3].

So how does one instruct Mathematica that it should instead evaluate f[f[1,2],3], or alternatively how does one work with infix operators? I'd be okay if I had to write my as f[a_List] instead, and then took care of things myself ...

-- Edit:

As the answer was deleted, note that making the function Flat is not the answer, here, as far as I can see.

-- Edit:

Here is an exact copy of the MMA file to reproduce this problem

In[13]:= f[a_,b_]:=a+b;
f[a_,b_,c_]:=f[f[a,b],c]
CirclePlus=f;
1\[CirclePlus]2\[CirclePlus]5\[CirclePlus]6
Out[16]= f[1,2,5,6]


You can tell it by making a definition what it should do if you have more then 2 arguments:

ClearAll[f];
f[a_, b_, c__] := f[f[a, b], c];
CirclePlus = f


Then you get

And of course you have to add the definition of f when it is called as binary function. So for instance, and only for the purpose of showing what happens:

f[a_, b_] := Row[{"(", a, "\[CirclePlus]", b, ")"}]


Here is how it looks when you use more than 3 terms. Note that the pattern is recursively applied until there are only 2 arguments in each call:

• This only works if I have only three terms; it doesn't make it generally associative (i.e. it doesn't work if there are 4 terms.) – Noon Silk Mar 22 '15 at 9:24
• @NoonSilk And you say this because you have tried it? – halirutan Mar 22 '15 at 9:43
• Yes, I did try it. Did you? – Noon Silk Mar 22 '15 at 9:44
• So you don't get the same result that I get for the 5 arguments in my last example? – halirutan Mar 22 '15 at 9:47
• No. This is what I have: In[13]:= f[a_,b_]:=a+b; f[a_,b_,c_]:=f[f[a,b],c] CirclePlus=f; 1[CirclePlus]2[CirclePlus]5[CirclePlus]6 Out[16]= f[1,2,5,6] – Noon Silk Mar 22 '15 at 9:49

halirutan demonstrated how to adapt your function f to handle multiple arguments but that changes the game: f is no longer a binary function.

The other aspect of this problem is that the CirclePlus operator itself is not binary; rather it accepts a series of arguments as illustrated in the question. CircleMinus is a binary operator, and with it your code works as written:

f[a_, b_] := a + b
CircleMinus = f;

q ⊖ r ⊖ s ⊖ t

q + r + s + t


This of course would be a confusing choice of operator for this function but it serves as illustration. An additional property that must be considered is left versus right association. CircleMinus is left-associative:

CircleMinus = foo;

q ⊖ r ⊖ s ⊖ t

foo[foo[foo[q, r], s], t]


Therefore is right-associative:

Therefore = foo;

q ∴ r ∴ s ∴ t

foo[q, foo[r, foo[s, t]]]


Care should be exercised when choosing an operator for your function!

• Well, in my case I'm actually performing a matrix direct sum, so I wanted the direct sum symbol. And that operation is associative. So how do I make CirclePlus be associative in the way I want? – Noon Silk Mar 22 '15 at 22:51
• @NoonSilk Theoretically you could edit the entry for CirclePlus in UnicodeCharacters.tr following the format described here (6363) but I strongly recommend against it as your code will only work on a similarly modified system. I recommend that you choose a different existing operator, or possibly create a new one as also described in the post linked above. – Mr.Wizard Mar 23 '15 at 3:40
• Yeah, I won't be editing that file. It seems crazy that I can't make this operator associative! – Noon Silk Mar 24 '15 at 21:46
• @NoonSilk I believe it is a design choice, not necessarily one that I defend, but at least one I think I understand. The operator associativity is a low-level property that affects parsing itself. User definitions are applied after parsing. Therefore to affect this one must edit low-level properties, i.e. UnicodeCharacters.tr. Mathematica simply isn't designed to allow low-level modification of the syntax itself; even resource files such as UnicodeCharacters.tr are only limited exceptions to this. One would have to write his own parser to define a truly custom language syntax. – Mr.Wizard Mar 25 '15 at 5:36