
Tim Bray doesn't know operator precedence rules - pw
http://www.tbray.org/ongoing/When/201x/2010/06/29/No-Defaults
======
jgrahamc
Good man. This is the sort of irrelevant detail beloved of pedants. It does
not make you a better programmer to know this sort of thing.

You probably should know your language's idioms, but this sort of detail is
not useful. I'd rather see a few extraneous parens around things that the
compiler can happily remove. This sort of attitude is why my Perl code tends
to be readable. There are all sorts of shortcuts and simplifications if you
know the edge cases of the language, but I'd rather have clarity than
cleverness.

e.g. my Perl coding style: [http://blog.jgc.org/2010/01/more-fun-with-toys-
ikea-lillabo-...](http://blog.jgc.org/2010/01/more-fun-with-toys-ikea-lillabo-
train.html)

~~~
DougWebb
That's a beautiful piece of code, and really interesting too. It's a great
example of how to document what the code is intended to be doing rather than
documenting what it's actually doing (eg: "add one to i"). I would maintain
your code any day.

~~~
jgrahamc
Thanks. If I expect a piece of code to survive any length of time I try to
document it well because I tend to forget how/why I decided to do things. In
that piece of code, I knew that I'd forget the trig. part quite quickly so I
figured an ASCII diagram was needed.

If you enjoyed that piece of code you might also enjoy the C code linked here:
[http://blog.jgc.org/2008/02/tonight-im-going-to-write-
myself...](http://blog.jgc.org/2008/02/tonight-im-going-to-write-myself-
aston.html)

Perhaps there should be a 'beautiful code' blog as a sort of counterpart to
the Daily WTF. I could reuse the domain usethesource.com.

Update: An there it is UseTheSource (<http://news.usethesource.com/news>).
Submit examples of beautiful or interesting code.

~~~
sophacles
Awesome! I hate seeing people say "Make good comments, not like X". I have
given up on asking "what would be a good comment" because no one seems to be
able to point to a good example. This will be much helpful :).

------
_delirium
I mostly do this, especially for mathematical expressions, but in some cases
languages have developed idioms where the common and readable style is to
leave out some parens. It's dumb to do it just as some kind language-lawyering
way to save chars, and it does raise the amount of background knowledge about
the language you need, but putting parens _everywhere_ can really break
readability as well.

For example, this is idiomatic and readable C (ignoring whether it's a good
idea to write this specific string-copy loop these days):

    
    
      while (*dst++ = *src++);
    

whereas this is line noise that you have to decode:

    
    
      while ((*(dst++)) = (*(src++)));
    

The first form does require you to know that ++ binds tighter than the
dereferencing operator, so the increment is incrementing the pointer, not the
value it points to. But it's easier to scan, and used enough that people who
code in C presumably can just glance at it. It makes a nice syntax pun due to
the interaction of the order of operators and the postincrement, too. You can
read it as: deref dst, then increment dst, which gives the nice intuition that
the deref happens, and then the increment happens. The parenthesized version
is more confusing on that point, and you'd probably just want to rewrite it
into a more verbose loop with 3 separate body statements, if you were going to
go that route.

Heck, even Java does this regularly. Method-call dot-chaining is idiomatic in
Java, even though it relies on an evaluation rule to work properly:

    
    
      foo.bar().baz().qux()
    

Not idiomatic:

    
    
      ((foo.bar()).baz()).qux()
    

For the same two reasons basically. The fully parenthesized version is too
noisy, and the unparenthesized version has a nice syntax-pun interpretation:
it's a "chain" of results going down the list of methods.

~~~
CountHackulus
I'd just like to point out that in your string example, you gain nothing by
keeping that string copy short. The compiler doesn't see lines, all it sees
are tokens, and what you've written there is fine for a compiler to read, but
difficult for a human.

Instead of adding parentheses, try writing it like this:

    
    
      while(*dst)
      {
        *dst = *src;
        dst++;
        src++;
      }
    

It's instantly more readably, it's very obvious what's going on, and you've
lost no performance. There's also no parentheses to add.

~~~
_delirium
I actually find that style considerably less readable, though admittedly I'm
quite familiar with C code. It's just less common for one (not the idiomatic
way of writing code in the language), but it also emphasizes this tedious
loop-iteration-at-a-time interpretation, while the original is easy to read as
a sort of Matlab-style single vector operation, once you're used to it ("copy
all the srcs to all the dsts").

Plus, once you start piling on a bunch of such code-explosions, you end up
with functions that are much harder to scan, because what could've been an
easy to scan 8-line function is pedantically written out as this super-
explicit 30-line thing.

------
smcl
I'm 100% with Tim here, I've never felt the need to memorise the order of
precendence for operators - as long as I've got my parens I'm happy. Luckily I
seem to work with others who feel the same way. If we did have someone
insistent on pushing the boundaries of readability I'd spend about a minute
looking up the precedence rules then another few weeks framing the perpetrator
for some real-life infraction as a form of punishment (depending on the
particulars this could range from petty theft all the way through to light to
medium treason)

~~~
lenni
Item #2 of The Zen of Python is my favourite:

    
    
        Explicit is better than implicit.

------
barrkel
I would draw the line at additive, multiplicative operators generally, but I
would also include &&, || and comparisons in C-derived languages (contra Tim).
Knowing the extra three precedence levels is a cheap investment that covers
such a wide range of commonly used languages - C, Java, C++, C#, bash's
let/for/etc.

I don't think it's necessary to have to parenthesize:

    
    
        u*t + a*t*t / 2.0
    

Working with Pascal (Delphi) quite a bit as I do, I also find this idiom -
required in Pascal with its limited number of levels - tedious:

    
    
        if (a > b) and (b < c) then // ...
    

The trouble is that you begin writing this:

    
    
        if a > b then
    

but updating it to add in the new conditional means you have to go back and
forth over the expression inserting parentheses. I think C and related
languages at the expression level make this better by making comparison
operators have a higher precedence to boolean operators.

Bitwise operators, of course, have an entirely different precedence level and
if you're using C, it's easy to get caught out:

    
    
        if (flags & MASK == FLAG1 | FLAG2) // cue much confusion

~~~
JoachimSchipper
I fully agree, but replace "much confusion" with "compiler warning".

~~~
barrkel
The only compiler I use that will warn for it is gcc, and even then you need
to use -Wall.

------
ewjordan
_A related case: I have never bothered to learn, nor will I, what the default
modifiers for Java’s variables and methods are. Thus, every one of those
things gets one of private or public or protected in front of it. There are
way better things to load up the finite cupboard-space in my mind with._

Oh, no, man, that's not good! "Default" visibility (package-private, i.e.
visible within the same package, but not outside of it) is there for a reason,
and that reason is that it's _not the same as public, private, or protected_!

There's literally no way to specify a package-private variable without leaving
the modifier off, though some people (including myself) like to write

    
    
      /*package-private*/
    

as the visibility, just to be explicit.

Aside from that nitpick, I agree with you, though, when in doubt, be explicit,
it will save you a lot of trouble in the long run.

------
kaffeinecoma
"I have never bothered to learn, nor will I, what the default modifiers for
Java’s variables and methods are"

That means that he doesn't understand "package" level access. There is no
"package" keyword (well, there is, but it means something else). To get
package-private access you have to leave it unspecified, so that means he
can't use this feature. Or grok it when he comes across it.

The lack of a keyword for this is a shortcoming in Java, IMHO. But even if you
don't use it often, you should have an inkling of how it works.

[http://stackoverflow.com/questions/403583/what-is-the-use-
of...](http://stackoverflow.com/questions/403583/what-is-the-use-of-package-
level-protection-in-java)

~~~
Tichy
It rarely ever seems to be useful, though?

~~~
loumf
I've used it for unit-testing -- gives the test class a little more access.

~~~
thomas11
Exactly. To elaborate a bit for those who never used it in that way: you want
to separate your unit tests from your app code. But you still want to give
your tests access to non-public methods in order to test them independently.
The solution is to put app code and tests in different folders, but in the
same packages, and make everything you want to test package-scoped.

------
chc
The problem is that Bray's reasoning could apply just as well to any aspect of
a language that can be worked around, and leads to meaningless bloat in every
case. Other examples:

"We shouldn't have to learn the standard library. Always implement functions
you want yourself, and comment what each line of code does."

"We shouldn't have to learn about variable scopes. Just put all your variables
at the top of the file."

Knowing the basics of operator precedence _should_ be expected. If you don't
know it, you don't really know the language. Bray even drops his own thesis
when his code sample assumes that the dot operator and function application
operator have higher precedence than logical-and.

There is definitely such a thing as expecting _too much_ familiarity with
operator precedence, but it's illogical to say that you shouldn't need to know
_anything_. These are the syntax rules of the language, people!

~~~
anamax
> Knowing the basics of operator precedence should be expected. If you don't
> know it, you don't really know the language.

What are "the basics of operator precedence" for C++?

Yes, I'm serious. I don't think that there's any agreement on that. At best,
there are a bunch of answers with significant overlap, and each non-trivial
organization has at least two answers.

That's why every non-trivial organization produces software which uses
multiple definitions with blurs between them for interfaces and common code.
And bugs.

C++ has almost 30 precedence levels and yet folks think that lisp is
unnatural.

~~~
chc
It's simply deceptive to use the words "C++" and "basic" in the same sentence.

~~~
anamax
Deceptive? Who is being deceived and about what?

Regardless, C++ seems to show that "Knowing the basics of operator precedence
should be expected." is unreasonable, at least wrt C++.

Note that C++ isn't all that complex wrt precedence, so the real problem is
with the claim. Humans can do about 10 levels of precedence. Since
demonstrating precedence knowledge is not the point of a programming
language....

------
jcromartie
Then Smalltalk is perfect for him, with no concept of operator precedence!

Kidding aside, this is smart. Defaults are things we shouldn't have to learn.
I use parens for anything they didn't drill into my head in grade school (but
in the aforementioned Smalltalk that doesn't work).

~~~
mbrubeck
Smalltalk, and Forth and Lisp too!

The simple parsing in these languages means that none of them supports normal
mathematical notation. But it also has benefits when it comes to extending
their syntax and building DSLs.

------
almost
Writing code that way I can understand. But it's kind of useful to be able to
read other peoples code and know what it does.

Also, "1 + 2 * 3" is quite obviously 6 and not 9 in languages with operator
precedence, I really don't think you need to write "1 + (2 * 3)".

Everything in moderation.

EDIT: hahaha, well I feel stupid. I'm leaving the incorrect answer there
because it's too funny not to :)

~~~
jsn
it's neither 6 nor 9 there, actually :) it's 7.

~~~
almost
You clearly don't understand the advanced kind of maths I'm doing there ;)

~~~
ramchip
Haskell to the rescue!

    
    
        ghci> let f = let 2*3=5 in 1+2*3
        ghci> f
        6

~~~
vijaydev
brilliant!

------
jules
I don't remember all the rules, but I do remember that comparisons come before
logical operations. It just doens't make sense to let a < b && c mean a < (b
&& c).

Perhaps an IDE/editor feature that removed unnecessary parenthesis could clean
up code and you'd learn the precedence as you go.

~~~
electrum
IntelliJ IDEA has intentions to "add clarifying parentheses" and "remove
unnecessary parentheses".

<http://www.jetbrains.com/idea/documentation/intentions.jsp>

~~~
jules
That's an interesting list. A lot of automatic code simplifications that I
want :)

------
billswift
The clearest statement of this I have seen is from the O'Reilly book
_Practical C Programming_ : "* and / come before + and -. Use parentheses for
everything else."

My general rule, on the rare occasions that I actually write code, is the same
as for other writing - write to be easily understood by potential readers. You
should take a little time and thought to make it easier for someone to follow
your work.

------
jergosh
Has been advocated before, notably in the Practice of Programming:

"Parentheses specify grouping and can be used to make the intent clear even
when they are not required. (...) Seasoned program- mers might omit them,
because the relational operators (< <= == ! = >= >) have higher precedence
than the logical operators (&& and ||). When mixing unrelated operators,
though, it's a good idea to parenthesix. C and its friends present pernicious
precedence problems, and it's easy to make a mistake."

~~~
kragen
Amusingly, I sent a note to the authors of TPOP when it came out claiming that
I had found a precedence error in some of the code in the book, between && and
==.

But I had gotten it wrong.

------
jonsen
How about the .-operator

    
    
      while ((calls.moveToNext)() && (count < howMany)) {
    

or

    
    
      while ((calls.moveToNext()) && (count < howMany)) {

~~~
barrkel
Java does not, as yet, have a kind of method or closure reference type, so
this ambiguity doesn't exist - the parentheses on the method call are not an
operator like in C++.

------
mtkd
Completely in agreement on this. I was a lone voice in a company where using
as few brackets as possible was a badge of honour.

~~~
eru
In a Lisp shop that would be a good thing. (I.e. getting by with less code.)

------
Gormo
This is an example of a good general principle for communication: don't
express your ideas in a way that a reader cannot understand without
referencing an external source of knowledge if it is a reasonably trivial task
to embed that knowledge into your content in the first place.

------
dododo
other things not worth filling your mind up with:

1\. type promotion rules

2\. method resolution order

3\. APIs for simple functions, just write your own--much more explicit.

4\. order of evaluation in "for (init; cond; inc)" loops and other nuances of
syntax/semantics.

------
kragen
I agree with him that it's good to include those extra parens in code you
_write_. But if you're reading or debugging code you didn't write, it's
important to know them. If you just assume the code means what it appears to
mean, you'll skip right over even shallow bugs.

I haven't read any of Tim's code, so I don't know how readable it is. But I
found that spending a lot of time reading other people's code dramatically
improved the readability of my own code. I venture to guess that his code is a
little opaque in places without meaning to be, as a result of his not spending
much time reading other people's code.

~~~
petewarden
> I found that spending a lot of time reading other people's code dramatically
> improved the readability of my own code.

This I wholeheartedly agree with. I spent the first five years of my career
porting large hairy codebases from PCs to embedded devices, without the
original programmers available, and that has given me a drastically different
code style to a lot of people.

> I venture to guess that his code is a little opaque in places without
> meaning to be, as a result of his not spending much time reading other
> people's code.

Here you lose me. I went out of my way to avoid memorizing the operator
precedence rules too well, so that when I saw a complex one-line expression
I'd have to stop and pay attention. A lot of the time the subtle bugs creep in
because the naked expressions flow in a way that looks seductively correct,
and so with an easy knowledge of precedence it's easy to make the same mistake
as the original author.

As Bjarne S once said about casting in C++, I want it to look ugly in the code
because it's an ugly idea. I want my code-reading to stumble when I hit those
long unparenthesized expressions, to make sure I pay attention.

------
simonw
Neither do I, for the exact same reason as Tim. Why bother relying on
precedence rules when your code is clearer if you use parenthesis? Even if you
know the precedence rules, there's no guarantee someone maintaining your code
will.

------
Anm
Regarding Java field modifier, its too bad the default is none of
public/private/protected.

In all other aspects, thumbs up to the post.

------
c1sc0
There are a lot of things you don't need to _know_ in order to use a language
fairly effectively: you can always look up syntax & things like operator
precedence. While that is a good strategy when you need to switch languages
frequently, it also means you'll never be an expert in language X. Which, for
plenty of programmers, is a _good thing_.

------
zwieback
It's readability vs. clutter - I think most programmers would allow
multiplication over addition without parens. It's logical to allow && over ||
since that's basically the same thing as * over +.

The one that always gets me is x == y&1, which is evaluated as (x==y) & 1.

------
bugsy
I know the rules for C (which are the worst of them) and yet I still use
parens all over the place. It's less brain burden to read, and if I want to
copy and paste it to javascript which has fewer precedence levels, it doesn't
break.

------
undersuit
He has a point, especially cause the rules can change.

<http://www.jsoftware.com/help/primer/order_of_eval.htm>

------
skn
Same here, but I find that questions on precedence often pop up during the
interview process and the interviewer wants to know details and he is not
satisfied with the parens.

~~~
eru
Yes, that's a bad interview question. I guess they do not care about you
knowing the precedences, but just use it as an easily tested proxy for your
general knowledge of the language.

I had interviewers ask about compiler flags. That was even more dreadful. I
said I knew Haskell, not that I knew GHC. (In the end, I could answer the
question, but they felt so wrong.)

------
javanix
For the record, _while (calls.moveToNext() && (count < howMany)) {_ will not
compile as written in Java without the interior parentheses.

------
njharman
For similar reasons I use almost no abbreviations (in variable/method/class
names).

------
st3fan
SO I guess they did not ask him that question at the Google Interview :-)

------
inerte
And this is one of the reasons why explicit is better than implicit.

------
sovande
Ridiculous, and miss out on boolean algebra and cool optimization
[http://sigpipe.macromates.com/2009/07/27/simplifying-
boolean...](http://sigpipe.macromates.com/2009/07/27/simplifying-boolean-
expressions/)

