77
$\begingroup$

I have always thought that f@g will give the same result as f[g] in all cases, and it is just a matter of style which one to use and that g will always evaluates first, and then f will evaluate using the result of g evaluation. I never thought that there can be any precedence issue here, since no one ever mentioned it in all the times I have been using Mathematica.

So I was really surprised when I found one case where this was not so. So my question is: How does one know when f@g is not the same as f[g] ?

The help says nothing about this (thanks to chat room for giving me the link to this, I searched and could not find it)

http://reference.wolfram.com/mathematica/ref/Prefix.html

Even though one can see the word precedence and grouping but no explanation of where these are talked about and no more links to follow

Prefix[expr, h, precedence, grouping] can be used to specify how the output form should be parenthesized.

clearly this is a precedence issue. But I have never seen this mentioned before any where.

Tr[Times @@@ {{2, 3}, {4, 5}}]

Mathematica graphics

Tr @ Times @@@ {{2, 3}, {4, 5}}

Mathematica graphics

Tr @ ( Times @@@ {{2, 3}, {4, 5}} )

Mathematica graphics

What seems to have happened is that in Tr@Times@@@.... the command Tr grabbed Times before Times was applied. You can replaced Tr by Total also and see the same effect.

ps. This is another reason for me to not use @ too much. I I really never liked to use @ and always liked the good old fashioned [] as it seems clearer also, and now safer also.

question is: What is the rule(s) of thumb to use? One should always look ahead and check before using @ to make sure precedence is met? Any other cases than this one might have to watch out for? If there are very few cases, may be one can add them to their cheat sheet. Where are the precedence of all operators listed so one can check?

$\endgroup$
4
  • 2
    $\begingroup$ you might want to look at @m_goldbergs answer here: mathematica.stackexchange.com/questions/19219/… $\endgroup$ Commented Aug 14, 2013 at 6:50
  • $\begingroup$ there are some hints in the following tutorials in the Mathematica Documentation Center: tutorial/OperatorInputForms; tutorial/SpecialWaysToInputExpressions; tutorial/DefiningOutputFormats $\endgroup$
    – bobknight
    Commented Aug 14, 2013 at 6:55
  • 3
    $\begingroup$ One issue is that Precedence cannot be easily found in the documentation. $\endgroup$
    – Yves Klett
    Commented Aug 14, 2013 at 7:24
  • 1
    $\begingroup$ Related: How to introduce Prefix operator with low precedence to avoid unwanted binding toward the left. $\endgroup$ Commented Sep 9, 2013 at 8:36

3 Answers 3

75
$\begingroup$

Operator Precedence Table

Unless one wishes to write in FullForm a competent Mathematica user must be familiar with at least the majority of syntax precedence rules, which are described in the Operator Precedence table.

Clarification: I do not mean that one must memorize (most of) this entire table be competent, but rather that one should know it well enough not to be surprised most of the time. Since memorizing the complete table is impractical (for me at least) I recommend having analysis tools at the ready when writing or reading code.

Here is an excerpt from that table:

enter image description here

It can be seen that expr1 @@@ expr2 is well below expr1 @ expr2 on the table which means that @ has greater binding power than @@@. In other words:

  • f @ g @@@ h is interpreted as (f @ g) @@@ h not f @ (g @@@ h)

You can see that there are a number of forms between expr1[expr2] and expr1 @ expr2 -- these are the cases where the two will behave differently in a potentially unanticipated way. For example:

  • Part: f @ g [[1]] is interpreted as f[ g[[1]] ] not f[g][[1]]
  • Increment: f @ g ++ is interpreted as f[g++] not f[g]++
  • PreIncrement: f @ ++ g is valid input: f[++g]

Of course the relatively high binding power of @ (see the rest of the table) means that many such things as f @ g + h are interpreted f[g] + h rather than f[g + h]. Most operators and input forms have lower binding power than @ so this behavior should be evident with minimal experimentation.

In addition to these the excerpt includes a couple of other interesting forms. The first is PatternTest which is unusual for having greater binding power than application brackets, therefore:

  • f?g[h] is interpreted as (f?g)[h] not f?(g[h])

The second is infix notation a ~f~ b (which many people know I am found of). This has lower binding power than @, and it is left-associative which means:

  • p @ q ~f~ i @ j ~g~ x @ y is interpreted as g[f[p[q], i[j]], x[y]]

Precedence function

There is an undocumented function Precedence that when applied a Symbol gives the precedence of the corresponding operator, if one exists. Here is my effort to match its output to the order declared in the table above:

{#, Precedence@#} & /@
 {PatternTest, default, Part, Increment, Decrement, PreIncrement, 
   PreDecrement, Prefix, InvisibleApplication, Infix, Map, MapAll, Apply} // TableForm

$\begin{array}{ll} \text{PatternTest} & 680. \\ \text{default} & 670. \\ \text{Part} & 670. \\ \text{Increment} & 660. \\ \text{Decrement} & 660. \\ \text{PreIncrement} & 660. \\ \text{PreDecrement} & 660. \\ \text{Prefix} & 640. \\ \text{InvisibleApplication} & 640. \\ \text{Infix} & 630. \\ \text{Map} & 620. \\ \text{MapAll} & 620. \\ \text{Apply} & 620. \end{array}$

I don't know if there is a Symbol that corresponds to expr1[expr2] but since the default precedence value (illustrated arbitrarily by default) matches its location in the table I don't think it matters.

$\endgroup$
7
  • $\begingroup$ That table is a complete answer but do you think my interpretation is correct? $\endgroup$
    – Kuba
    Commented Aug 14, 2013 at 7:45
  • $\begingroup$ @Kuba Since Precedence is undocumented I am uncertain of your application and its authority; I prefer to reference the table instead. $\endgroup$
    – Mr.Wizard
    Commented Aug 14, 2013 at 7:47
  • 3
    $\begingroup$ @LeoFang It would be better familiarize yourself with the syntax table so that each case can be handled most efficiently however there is nothing wrong with using extra parentheses. I personally find that limiting the use of parentheses enhances readability of my own code as I know that they are usually there for a purpose. You can also use the application bracket form rather than parentheses e.g. Map[f, # + 2 & @ g] instead of (f) /@ (# + 2 & @ g). $\endgroup$
    – Mr.Wizard
    Commented Aug 14, 2013 at 7:53
  • 1
    $\begingroup$ Mr.Wizard I largely agree, but I think still a lot can be learned from Precedence. Just to realize that prefix, infix and postfix notations are all governed by comparing their precedence-numbers is great, I think. Especially that the number for a postfix notation can be compared with that of a prefix one. So you can have all notations in a row in your mind and induce "relative precedences" by transitivity. The Precedence function can then help to get good examples, like your f@g++, which makes you realize ++ has higher precedence than @. (and therefore higher than // etc) $\endgroup$ Commented Aug 14, 2013 at 8:05
  • 2
    $\begingroup$ @JacobAkkerboom You should take all your comments and put them into an answer :) $\endgroup$
    – Kuba
    Commented Aug 14, 2013 at 8:14
18
$\begingroup$

If you are looking for complete answer, take a look at Mr. Wizard's :)

Also, see the comments of @JacobAkkerboom below, who proved I was too hasty. :)

I was right that the function OP is asking about at the end is Precedence but I was wrong in my interpretation of what is happening.

I will leave this for future visitors as it is not so obvious.

Also, everyone that upvoted, feel free to un-upvote if you wish :)

right part:


Precedence of functions is given by Precedence :)

More here: What are some useful, undocumented Mathematica functions?

"Good old fashioned" [] is safer but I really like @, I just have to remeber what is going to happen basing on my experiece, because no one will remember all precedences :)

In fact, sometimes I like to do f @ ( some code ). The more different brackets, the more transparent code is, IMO.


wrong part

Precedence[Apply]
Precedence[Compose]
620
670

So that's why Tr[Times] is done before Times is applied to the list.

What is also an answer to your question about precedences of functions. It is Precedence, an undocumented function.

There is a discussion about what @ is. In my opinion f @ g does not mean that there's operation Prefix with f on g. Prefix is only a syntax form(?). What is happening is:

Compose[f, g]

That's why I've checked Precedence of Compose.

More about Compose: Why there is no name... (this link is true itself :P)


As you see the wrong part is longer...

$\endgroup$
21
  • 1
    $\begingroup$ @Nasser That's why we all should go back to main Q&A often :) What are some useful.. $\endgroup$
    – Kuba
    Commented Aug 14, 2013 at 6:52
  • 1
    $\begingroup$ I spend more than one hr searching on this before, and also asked on chat. I could not even find help on @ since Mathematica ?@ gives nothing. It is very frustrating why one can't find help on @ when it is one of the most used symbols around. I had no idea it is called Prefix and did not even know there was a precedence function. $\endgroup$
    – Nasser
    Commented Aug 14, 2013 at 6:58
  • 2
    $\begingroup$ @Nasser about documentation, it is really great on the beginning. Later, when one is starting asking deeper question it can be really annoying to find the answers one is looking for. :/ $\endgroup$
    – Kuba
    Commented Aug 14, 2013 at 7:25
  • 3
    $\begingroup$ Kuba, actually the example by Mr.Wizard shows why it is about Prefix. f@g++ gets parsed to f[g++]. This is because @ has lower precedence than Increment. We can see that indeed Precedence[Increment]==660. So if the precedence of @ was really 670, it would have been parsed as Increment[f[g]]. Note that you can never get Mathematica to show you an expression with @ in it in output. It is really a matter of parsing, Mathematica forgets how the expression was entered. I think no function like Compose is used as it would feel strange to me to use such a function in parsing code. $\endgroup$ Commented Aug 14, 2013 at 7:47
  • 2
    $\begingroup$ Compare also Hold[f@g ..] and Hold[f@g++]. I think you cannot explain the difference if you think the precedence of @ should be 670 :) $\endgroup$ Commented Aug 14, 2013 at 7:51
2
$\begingroup$

I was making a custom typesetting form (MakeBoxes[] et al.), and happened to notice that Precedence[] works on box forms. This lets you get the precedences for things like F[x] or F@x (I actually mean F@x, not Prefix@F@x or similar). The one shortfall I noticed is that when fed bare symbols (like in Precedence@"F", where the double-quotes are actually the normal box-representation for such a thing), the precedence for a string is used, rather than the default precedence for a symbol without any built-in precedence assignment.

Anyways, here's a handy table for some of the basic "otherwise not enumerable via make a method like Table[ Precedence@ToExpression@#, Names[...] ].

Code:

Grid[#, Frame -> Thick,
   Dividers -> {All, {All, 2 -> Thick}},
   ItemStyle -> {Automatic, {Bold}},
   Background -> {Automatic, {{LightGray, Automatic}}}
   ] &@
 Prepend[{"Prec", "Expr", "Raw"}]@
  Sort@Map[Through@*{Precedence, ToExpression, RawBoxes}]@{
     "F",
     RowBox[{"(", "F", ")"}],
     RowBox[{"F", "[", "x", "]"}],
     RowBox[{"F", "@", "x"}],
     RowBox[{"(", RowBox[{"F", "@", "x"}], ")"}],
     RowBox[{"x", "//", "F"}],
     RowBox[{RowBox[{"F", "[", "a", "]"}], "[", "x", "]"}],
     RowBox[{RowBox[{"F", "[", "a", "]"}], "@", "x"}],
     RowBox[{RowBox[{"(", RowBox[{"F", "@", "a"}], ")"}], "[", "x", 
       "]"}],
     RowBox[{RowBox[{"(", RowBox[{"F", "@", "a"}], ")"}], "@", "x"}],
     RowBox[{"F", "@", RowBox[{"G", "[", "x", "]"}]}],
     RowBox[{"F", "@", RowBox[{"(", RowBox[{"G", "@", "x"}], ")"}]}],
     RowBox[{"F", "@", RowBox[{"G", "@", "x"}]}],
     RowBox[{"F", "[", RowBox[{"x", ",", "y"}], "]"}],
     RowBox[{"x", "~", "F", "~", "y"}],
     RowBox[{"3", "x"}],
     RowBox[{"3", "+", "x"}],
     Prefix,
     Infix,
     Postfix,
     Construct,
     Times,
     Plus
     }

Output:

Precedence Values of Box-Forms of Expressions

If anyone wants me to clean-up-and-post a copy of e.g. PrefixForm[...], let me know. I have too many forked versions to post any single one at the moment, but I use is all the time and find that it makes digesting output mentally easier. Like e.g. MatrixForm, the kernel just sees a single wrapper, but the front-end formats the output differently. When re-evaluated as input, the wrapper goes away, via InterpretationBox. Pretty simple but some of the bells-n-whistles were a bit of a pain, like coming up with an exclusion list so that e.g. {1} doesn't format as List@1, HoldForm@F@x does format as F@x, stray uses of Prefix@F@x still just format as F@x, nasty things like Definition@F only transform when you really want them to, held expressions aren't expanded, repeated calls to PrefixForm don't mess-up the output, etc.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.