Honestly, most of the time I think we would be better off without operator precedence. It just adds another thing you need to keep in your head when reading code.
Unfortunately, nearly everyone -- even non-programmers -- learned the operator precedence for arithmetic operators, which means they might be confused if those operators in a language didn't use it.
Just saw this. That is not my SO question -- I'm just a lifetime programmer who has never seen rewriting of operator precedence in the tens of languages I've used.
My programming teacher told me: "operator precedence is complicated, always use parenthesis if you have multiple operators in a single expression". I simply do that, and nobody complained so far :)
Me too! So far I have seen four actual bugs in large numerical code bases that were caused by overlooking operator precedence. I expect to see more in the years to come.
I think that precedence of '*' over '+' is acceptable (as everyone knows it instinctively) but I would love a way to require parenthesis for everything else.
Well, order of precedence rules are much more complex in programming languages, and are not the same across languages. Mixing math with logic and bitwise operators without explicit parens is a classic "newbie" mistake.
Well yeah, having precedence rules makes the notation more concise and can save you from typing lots and lots of brackets. And I don't think multiplication/division having higher precedence than addition/subtraction (and, by extension, AND having higher precedence than OR) is all that "screwball" - and even if it were, if you paid attention in elementary school, you already know it, so programming languages can rely on it. Of course, the moment they start getting "creative" with precedence, those exceptions turn into massive footguns...
Interesting. I've wondered about this when making an expression parser. Obviously it makes parsing way easier and mistaken precedence is often a cause of bugs (especially in C where some of the operator precedence is plain wrong). But on the other hand that's got to be quite annoying surely?
The lack of operator precedence has no relationship with the mandatory use of parentheses.
For example the APL syntax for expressions, which I prefer, is that there is no operator precedence.
The operands are associated to operators strictly from the right to the left, regardless which operators or functions are used, which is a much wiser choice than the reverse traditional order of evaluation.
No parentheses are used, except when they are needed to modify the default evaluation order.
Indeed. I just never really internalized all the operator precedence in C/C++ so I never write code like `a + b >> c`; I always add parenthesis when mixing arithmetic and bit operations.
For language-specific operators I could understand ... but to me, the cognitive load of the parentheses is worse than having to think for a moment about this particular set of operators which have the same precedence in every language I've used (and the arithmetic operators which I've had to know the order of since early grade school).
The operator precedence in the article is just an example of a principle that does hold: A series of choices, each individually plausibly the right call, lead to a bizarre situation that doesn't feel right.
However, often (and I submit this very article as exhibit A), the logic is reversed: One observes a bizarre scenario, points at it, and goes: I don't know what or how, but clearly somebody somewhere messed up.
That's not true; sometimes seemingly simple things simply aren't simple, and you need to take into account all users of a feature and not just your more limited view.
Take operator precedence. __operator precedence is an intractable problem__.
Some languages try to make it real simple for you and say that all binary operators are resolved left to right, and have the same precedence level. This makes it easy to explain and makes it much simpler to treat anything as an operator; a feature many languages have. Smalltalk works like this. The smalltalk language spec fits on a business card; obviously, you must use such principles as C's operator precedence table would otherwise occupy most of your card!
But that does mean that `1 + 2 * 3` is 9 and not 7, and that is extremely weird in other contexts.
So, you're in a damned if you do and damned if you don't situation: There is no singular answer: No operator precedence rule is inherently sensible regardless of the context within which you are attempting to figure out how operator precedence works: It is an intractable problem.
One way out is to opt out entirely and make parentheses mandatory. If you then also make it practical and say that the same operator associates left to right regardless of what operator it is, you can still write, say, `1 + 2 + 3 + 4`, but you simply aren't allowed to write `1 + 2 * 3` – you are forced to write `1 + (2 * 3)` or `(1 + 2) * 3`. But now anybody who feels they can copy problems from math domains, or from technical specifications such as a crypto algorithm description now gets tripped up. You may disagree (I certainly do), but a significant chunk of programmers just prefer shorter code. I would certainly prefer my languages to work this way, and have configured my linters like this as well, but it's still not a universally superior solution regardless of point of view.
In other words, had Ritchie chosen to go with this 'when in doubt, do not compile it' strategy, this article could not be written. And we'd still have programmers unhappy with how the operator precedence rules work.
APL was the first language I learned in school and I was thrown by the precedence of the mathematical operators, but once the other operators were put in play, it was an incredibly simple rule -- and rarely did I or other APL developers have bugs relating to order of operation.
I then moved to C++ and was gobsmacked the the precedence rules and was forced to use parentheses to get things right. I have seen hundreds of bugs produced by programmers that tried to be clever and avoid parens relying on their faulty memory of the precedence priorities.
Just look at the C++ Operator Precedence table listed at the following URL. It's wild!
I do too, and it's fine as long as you (a) have a relatively small number of operators, and (b) use one language, or several that have conforming precedence.
Does "<<" in C have the same precedence as "shl" in Pascal? How does it compare to multiplication, of which it is (essentially) a specialization? Does a<b<c in C mean what it does in Math? What about Python?
When I learned APL (and J and K), the first instinctive response to the lack of operator precedence was wtf? -- all same precedence, all "right associative" / "right to left" / "left of right" / "long right scope" (same meaning, different terms).
But after using it for a day, I realized all the other programming languages have it wrong. Math notation gets a pass because you handwrite it, so a set of rules that minimizes writing does make sense. Not so for programming languages.
APL/J/K have tens, perhaps even a hundred, operators -- so there isn't really any other practical way. But it just works so well, that it puts the Algol/C/Pascal decision to copy math in an unfavorable light.
I don't remember having problems with the way operator precedence work in any languages I worked with. May be I don't write complicated programs as you guys do.
Most of the time operator precedence works according to the BODMAS rule. Doesn't it?
Unfortunately, nearly everyone -- even non-programmers -- learned the operator precedence for arithmetic operators, which means they might be confused if those operators in a language didn't use it.
reply