Live data from Hacker News

Dennis Ritchie on the priorities of && || vs. == etc. (1982)

lysator.liu.se

71–80 of 178 posts

Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)

#71
post #44
post #9

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.

Off the top of my head I can’t think of anything that should bind more weakly than the equivalence.

Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)

#72

I 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.

It bothered me a while for "short" boolean expressions to have a linter expect parens, where I'd simultaneously expect everyone with a high school degree to understand the implicit operator precedence.

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)

#73
post #46

Earlier 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`.

That's just the way C is. If you want to check "truthiness" (as much as you can in C), just do 'if x'.

Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)

#74

I 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.

I once implemented a logical expression evaluator to be used as filters on a search page. My boss tested it and filed a bug because he expected OR to have higher precedence than AND. I pointed him to a page with the rules and told him that he could use parenthesis if he wanted to modify the order of precedence. He was sort of convinced but never closed the ticket. Every release he would move it to the next release.

Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)

#75

Earlier 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.

I think most people agree "a*x**b + c" is more clear than "(a*(x**b))+c". Or "a+b+c+d" is more clear than "a+(b+(c+d))".

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)

#76
post #8

Earlier 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?

xor is more like a substraction...

Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)

#77
post #9

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.

> match the traditional precedence in logical expressions

arithmetic expressions?

Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)

#78
post #70

I 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...

This article is a joy to read.

Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)

#79

I 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…

What about using the same associative operator multiple times?

Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)

#80

I 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.

|| is lower precedence than &&. I memorized that, just like I memorized that + is lower precedence than *.

There are some languages (e.g. shell) where they have the same precedence.

Prettier (JavaScript) adds parens like you suggest automatically.

Post reply on HN