The relative priorities of && vs ||, or & vs |, match the traditional precedence in logical expressions: "and" binds more tightly than "or", just as * binds more tightly than + ("and" is equivalent to * for one-bit values, and "or" is addition modulo 2). So I think that they got this correct. However, the precedence of & vs &&, or & vs ||, etc is a source of problems.
& vs && doesn't feel like a problem to me. & vs == is the real problem: `(val & MASK) == CONSTANT` needs parentheses due to this mistake. `a & (b == c)` essentially almost never makes sense (== gives you a boolean, and when dealing with booleans you can use && instead), yet that it what you get by default if omitting the parentheses.
Dennis Ritchie on the priorities of && || vs. == etc. (1982)
71–80 of 178 posts
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#72I don't even know the priority between && and ||. If I'm using both, I use parentheses just so it's more explicit. "a && b || c" should flag a linter, IMO, with "(a && b) || c" or "a && (b || c)" being required.
Then, since my first bug having been merged that was caused by a && vs || operator precedence mistake, I like my parens-always ESLint rule (or whatever exactly it was called).
Even redundant parens can start to look as pleasent as indents, after getting used to them.
In short, I think expressions like (a && b || c && d || e) are a footgun and linters should forbid them. Parens fit well with logical thinking, similar to relative clauses in language.
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#73Earlier quoted context omitted.
IMO the intuition is to not use any intuition at all: there aren't built-in booleans in C, true is a #define for 1 and false is a #define for 0. For C conditionals, 0 = false, nonzero = true. So a+b != 0 a!=0 or b!=0 a*b != 0 a!=0 and b!=0 Of course this intuition also reveals the pitfall behind this correspondence! You'd better make sure those are unsigned ints or #defined booleans, so you're not using general C exp…
"true is a #define for 1" is bad idea. Because when `x` is, say, `2` then `if x` is not the same as `if x==true`.
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#74I don't even know the priority between && and ||. If I'm using both, I use parentheses just so it's more explicit. "a && b || c" should flag a linter, IMO, with "(a && b) || c" or "a && (b || c)" being required.
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#75Earlier quoted context omitted.
Sorry, but I'm of the exact opposite opinion. If you don't know, learn. It's not hard (as other sibling comments have noted). Code with superfluous parentheses is even more confusing, since I expect them to be present only when overriding precedence. ...and I just realised your username adds some additional irony.
Explicit is better than implicit. I think the real problem is not breaking up complicated expressions. If it's more than just a few pairs of parentheses making it hard to read there's something more wrong there.
Why are we happy to avoid parentheses for these operations but not for && and ||? Probably because we are all really used to the precedences for + and *.
So at the end of the day, what's more clear depends on How familiar the engineers working on your code are with a given set of operators.
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#76Earlier quoted context omitted.
Convert them to arithmetic. If you ignore the casting, a && b is just a * b a || b is just a + b Now you remember the precedence between them (except in broken languages, of which the only notable one is shell).
Isn't it x ^ y which is like x + y?
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#77The relative priorities of && vs ||, or & vs |, match the traditional precedence in logical expressions: "and" binds more tightly than "or", just as * binds more tightly than + ("and" is equivalent to * for one-bit values, and "or" is addition modulo 2). So I think that they got this correct. However, the precedence of & vs &&, or & vs ||, etc is a source of problems.
arithmetic expressions?
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#78I don't even know the priority between && and ||. If I'm using both, I use parentheses just so it's more explicit. "a && b || c" should flag a linter, IMO, with "(a && b) || c" or "a && (b || c)" being required.
You’re in good company[1]: Do not introduce priority rules that destroy symmetry. I remember how much more pleasant the predicate calculus became to work with after we had decided to give con- and disjunction the same binding power and thus to consider p ∧ q ∨ r an ill-formed formula. [1] https://www.cs.utexas.edu/users/EWD/transcriptions/EWD13xx/E...
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#79I don't even know the priority between && and ||. If I'm using both, I use parentheses just so it's more explicit. "a && b || c" should flag a linter, IMO, with "(a && b) || c" or "a && (b || c)" being required.
The Ada language requires explicit parentheses in the case of a succession of different logical operators precisely to avoid precedence-related bugs. [0] In the Pony language, any expression where more than one infix operator is used must use parentheses to remove the ambiguity. [1] The Zig language considered following Pony, but didn't. [2] [0] http://archive.adaic.com/standards/83rat/html/ratl-03-06.htm... [1] http…
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#80I don't even know the priority between && and ||. If I'm using both, I use parentheses just so it's more explicit. "a && b || c" should flag a linter, IMO, with "(a && b) || c" or "a && (b || c)" being required.
There are some languages (e.g. shell) where they have the same precedence.
Prettier (JavaScript) adds parens like you suggest automatically.