Skip to main content

programming - when is f@g not the same as f[g]?



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?



Answer




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.


Comments

Popular posts from this blog

plotting - Plot 4D data with color as 4th dimension

I have a list of 4D data (x position, y position, amplitude, wavelength). I want to plot x, y, and amplitude on a 3D plot and have the color of the points correspond to the wavelength. I have seen many examples using functions to define color but my wavelength cannot be expressed by an analytic function. Is there a simple way to do this? Answer Here a another possible way to visualize 4D data: data = Flatten[Table[{x, y, x^2 + y^2, Sin[x - y]}, {x, -Pi, Pi,Pi/10}, {y,-Pi,Pi, Pi/10}], 1]; You can use the function Point along with VertexColors . Now the points are places using the first three elements and the color is determined by the fourth. In this case I used Hue, but you can use whatever you prefer. Graphics3D[ Point[data[[All, 1 ;; 3]], VertexColors -> Hue /@ data[[All, 4]]], Axes -> True, BoxRatios -> {1, 1, 1/GoldenRatio}]

plotting - Filling between two spheres in SphericalPlot3D

Manipulate[ SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, Mesh -> None, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], {n, 0, 1}] I cant' seem to be able to make a filling between two spheres. I've already tried the obvious Filling -> {1 -> {2}} but Mathematica doesn't seem to like that option. Is there any easy way around this or ... Answer There is no built-in filling in SphericalPlot3D . One option is to use ParametricPlot3D to draw the surfaces between the two shells: Manipulate[ Show[SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], ParametricPlot3D[{ r {Sin[t] Cos[1.5 Pi], Sin[t] Sin[1.5 Pi], Cos[t]}, r {Sin[t] Cos[0 Pi], Sin[t] Sin[0 Pi], Cos[t]}}, {r, 1, 2 - n}, {t, 0, Pi}, PlotStyle -> Yellow, Mesh -> {2, 15}]], {n, 0, 1}]

plotting - Mathematica: 3D plot based on combined 2D graphs

I have several sigmoidal fits to 3 different datasets, with mean fit predictions plus the 95% confidence limits (not symmetrical around the mean) and the actual data. I would now like to show these different 2D plots projected in 3D as in but then using proper perspective. In the link here they give some solutions to combine the plots using isometric perspective, but I would like to use proper 3 point perspective. Any thoughts? Also any way to show the mean points per time point for each series plus or minus the standard error on the mean would be cool too, either using points+vertical bars, or using spheres plus tubes. Below are some test data and the fit function I am using. Note that I am working on a logit(proportion) scale and that the final vertical scale is Log10(percentage). (* some test data *) data = Table[Null, {i, 4}]; data[[1]] = {{1, -5.8}, {2, -5.4}, {3, -0.8}, {4, -0.2}, {5, 4.6}, {1, -6.4}, {2, -5.6}, {3, -0.7}, {4, 0.04}, {5, 1.0}, {1, -6.8}, {2, -4.7}, {3, -1....