# Change associativity of the @ operator

The @ operator in Mathematica is right-associative by default, i.e.

f@g@h


evaluates as

f@(g@h)


Is it possible to make the @ operator evaluate the involved functions in a left-associative order (f@g)@h instead?

-
I'm just curious... what are the use cases you have in mind? –  sebhofer Oct 11 '12 at 13:29
Using J/Link you can do obj@method1[args]@method2[args2] and it will evaluate correctly from left to right. I want to mimic that method invocation syntax. –  sakra Oct 11 '12 at 13:38
Couldn't you use //? –  sebhofer Oct 11 '12 at 14:06
Actually I think it was an error by Wolfram to do this. They should have used another operator with the correct associativity, or maybe even invented a completely new one. Or even better, just used normal expressions with the object passed as first argument (i.e. method1[obj, args]). And if they wanted to have objects to the left, provide a general syntax (e.g. an extended infix syntax, transforming a~b~[...] into b[a,...], so you could write obj~method~[args], but also e.g. 5~IntegerDigits~[2,3]). –  celtschk Oct 11 '12 at 16:37
@celtschk That would be an interesting syntax. I can only imagine the resistance it would be met with however, as even simple ~infix~ has been a hard sell. :^) –  Mr.Wizard Oct 11 '12 at 16:50

## 2 Answers

The problem is that the conversion happens at parsing stage, not evaluation. And after code has been parsed, the details of how function was invoked (prefix, normal way or postfix) are not stored any more, so by the time you evaluate the code, you have no way to tell whether you typed it as f@g@h, f[g[h]], or h // g // f.

In the FrontEnd, you can do something like this:

Clear[fn];
fn[RowBox[{f_, "@", rest_}]] := fn[f, rest];
fn[before_, RowBox[{f_, "@", rest_}]] :=
fn[RowBox[{"(", RowBox[{before, "@", f}], ")"}], rest];
fn[before_, last_] := RowBox[{before, "@", last}];
fn[x_] := x;


followed by

\$PreRead = fn;


Then,

f@g@h

(* f[g][h] *)


Note that the above code may not be totally robust, since it is based on interpreting box expressions, and I may have missed some possibilities. It should be possible to make it reasonably robust though, by extending to more cases.

Since a single @, as far as I know, does not have any other meaning in Mathematica (other than a prefix function call), another option you have is to write a string preprocessor which will be called to preprocess your code before it is parsed by Mathematica parser, inserting parentheses as necessary. This method can probably be made to work for packages as well.

-

A similar question has been addressed here:

How can one define an infix operator with an arbitrary unicode character?

I strongly encourage you to add an operator, if necessary, rather than changing the behavior of the built-in one.

Nevertheless, if you are undeterred might be able to make this change in a similar fashion but I expect it to break the system if you are successful.

-
One problem with this seems to be that anyone else who'd like to use the code with that new operator would have to change their UnicodeCharacters.tr file as well. –  Leonid Shifrin Oct 11 '12 at 16:55
@Leonid absolutely, but anyone who is going to hack @ to behave differently shouldn't be sharing code anyway! :-@ –  Mr.Wizard Oct 11 '12 at 16:58
The general solution to this problem is to write a programmable preprocessor for Mathematica (for some languages like OCaml, such preprocessors exist), which would allow one to define an arbitrary syntax. If such a thing appears and becomes mature and robust, then code using it could be shared, I think. Until then, I tend to agree with you. –  Leonid Shifrin Oct 11 '12 at 17:11
That would be very useful. Let's try to talk to relevant people next week at the conference. I really think that metaprogramming is an extremely nice and unique feature of Mathematica and should be improved. –  Rolf Mertig Oct 11 '12 at 17:59
@RolfMertig I have been thinking about implementing this for quite some time. Perhaps will move that up on my todo list. We can discuss during the conference. –  Leonid Shifrin Oct 11 '12 at 18:43