30
$\begingroup$

I've been using Mathematica for years, and over time I have developed the habit of using:

Select[data, (# == 1 &)]

instead of

Select[data, # == 1 &]

I learned this by mimicking the style of more experienced users. I'm pretty sure that there are reasons for flanking the function with parentheses, but I'm not sure that I have seen a reason for why this is necessary or a good habit to get into. Would someone be able to comment?

$\endgroup$

3 Answers 3

28
$\begingroup$

It is a good habit to get into because you can often get tripped up by precedence rules (no one remembers everything!). For instance, PatternTest binds very tightly. See the difference between these two definitions:

Clear@f
f[_?(# == 2 &)] := Print@"foo"
f[_] := Print@"bar"
f[2]
(* "foo" *)

Clear@g
g[_?# == 2 &] := Print@"foo"
g[_] := Print@"bar"
g[2]
(* "bar" *)

You can see that the second function does not behave as expected. Further inspection of the patterns will show that the function is not being defined as expected:

_?#1 == 2 & // FullForm
(* Function[Equal[PatternTest[Blank[],Slot[1]],2]] *)

_?(#1 == 2 &) // FullForm
(* PatternTest[Blank[],Function[Equal[Slot[1],2]]] *)

A similar situation arises when you're supplying a pure function to options such as ColorFunction, Mesh, etc.

$\endgroup$
3
  • 1
    $\begingroup$ On the other hand, I probably wouldn't use parentheses in functions like Select or Split unless needed. $\endgroup$
    – rm -rf
    Oct 16, 2012 at 5:00
  • 4
    $\begingroup$ Another typical grr-case is in rules, like ColorFunction -> 3 # & $\endgroup$
    – Rojo
    Oct 16, 2012 at 5:20
  • 7
    $\begingroup$ "There is no parenthesis shortage yet; if the parentheses clarify your code's intent, don't hesitate to put them in." $\endgroup$ Oct 16, 2012 at 5:22
23
$\begingroup$

I like to use Ctrl+. to discover how it's grouped. For example, in this example:

Plot3D[Sin[x y], {x, 0, 3}, {y, 0, 3}, ColorFunction -> Hue[#] &]

Putting your cursor position after & and pressing Ctrl+. two times, you will get all expression ColorFunction -> Hue[#] marked, so it's wrong, and you need to put () like this:

Plot3D[Sin[x y], {x, 0, 3}, {y, 0, 3}, ColorFunction -> (Hue[#] &)]

And now, if you do the same test, you get just Hue[#] &marked, that is what we need.

In your example (Select[data, # == 1 &]) you can test and see that you get the right grouped form, so it's not necessary.

$\endgroup$
2
  • $\begingroup$ I use the same method, among others. +1 $\endgroup$
    – Mr.Wizard
    Oct 16, 2012 at 13:31
  • $\begingroup$ @Murta It is a nice approach. Could you please kindly explain what in general makes this Ctrl+Dot operation? Not only in regard to this particular problem, but in a more general context. $\endgroup$ Apr 9, 2013 at 8:20
17
$\begingroup$

R.M chose PatternTest as an example but I find that subtly misleading. PatternTest is highly unusual because it binds tighter than [ ], meaning x_?head[arg] parses as (x_?head)[arg], but even without this behavior the parentheses would be needed.

In your own example the parentheses are unnecessary and, being a fan of terse coding, I suggest you leave them out unless the bounds of your function are unclear. There is no ambiguity in Select[ data, # == 1 & ] and it is easy to see the function's bounds.

In longer sections of code parentheses can be helpful for visual (human) parsing but I usually favor line breaks for that purpose. I feel that these are more visible and their purpose more clear.

As alluded to in the second paragraph there are of course times that the parentheses are needed, as well as times they can improve readability. There are two different placements and both, sometimes together, have a place.

The first form: ( body & ) is useful for limiting the reach of &, while the second: ( body ) & is useful to extend it. I feel that reserving them for these purposes makes their meaning more clear.

One sees from the precedence table that & is fairly far down the list, so a natural reading of & is to consider its body to be most things to the left side, bounded by Set-type operators or CompoundExpression: ; (and of course ,). (Yes, there are other possible bounds but these are by far the most common in practice.) Reading my own code if I used ( ... &) it tells me that the bound needed to be limited, e.g.:

5 + (Sqrt[#] &) /@ {1, 2, 3}

Union[list, SameTest -> (Mod[#1, 3] == Mod[#2, 3] &)]

Conversely if I used ( ... ) & I know that I wanted to extend the bound, e.g.:

(# = #2) & @@@ {{a, 1}, {b, 2}, {c, 3}}

$PrePrint = (Print@#; #) &

From my perspective sprinkling parentheses needlessly only obfuscates the function of the code and I wish to avoid that, but there is some subjectivity even within these guidelines and I don't mean to imply that parentheses should be used only when syntactically necessary.

Consider:

NestWhile[# + 1 &, 888, ! PrimeQ[#1] || ! PrimeQ[#3] &, 3]

In my opinion putting ( ) anywhere in the first argument is pointless as this is already as clear as it possibly can be. The second & is a more interesting case. I would not use the ( body &) form because as I see it ..., ( stuff ), ... is redundant: commas already serve to group expressions so the ( ) tell me nothing. I might use ( body ) & if I or someone likely to read the code may not always remember the precedence of || versus &:

NestWhile[# + 1 &, 888, (! PrimeQ[#1] || ! PrimeQ[#3]) &, 3]

Here the ( ) do at least tell me something that is not already apparent from the commas: the function body extends through the bounded expression.

$\endgroup$

Your Answer

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

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