Live data from Hacker News

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

lysator.liu.se

131–140 of 178 posts

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

#131

Earlier quoted context omitted.

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.

Just nitpicking: "a+b+c+d" in C is equivalent to "((a+b)+c)+d" not to "a+(b+(c+d))".

I otherwise agree with your comment: in most cases, unnecessary parentheses make the code slower to read, just like unnecessary "==true".

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

#132
post #71
post #44

Earlier quoted context omitted.

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

Really? Do you think equivalence should be weaker than && and || so that you would write

  if ((a==0) && (b==0))
instead of

  if (a==0 && b==0)

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

#133
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).

My problem here is that I distinguish between multiplication and addition by seeing which one distributes over the other. a * (x + y) = (a * x) + (a * y) However, the reverse doesn’t work… a + (x * y) =? (a + x) * (a + y) Why is this a problem? a ∧ (x ∨ y) = (a ∧ x) ∨ (a ∧ y) a ∨ (x ∧ y) = (a ∨ x) ∧ (a ∨ y) Both are true. So, who are we to say that one corresponds to multiplication, and the other corresponds to addit…

Actually if you think about Boolean logic as mod 2 arithmetics xor is addition, rather than or.

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

#134
post #8

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.

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

Depends on the shell. Murex, for example, follows order of precedence correctly

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

#135
Please note that, despite the misleading title, TFA is about the precedence of bitwise operators & and | with respect to the comparison operators (== and all the others). In particular it was asked to Ritchie why the former are weaker than the latter in C, a rule generally considered a mistake because it makes it impossible to write common expressions like

  if (addr & mask == 0)
without adding extra parentheses:

  if ((addr & mask) == 0)
TFA is not about the relative precedence between & and | (which is well understood, although disputed, and has mathematical basis), or between && and || (which mimics & and |). And TFA is not even about the precedence of the logical operators && and || vs. the comparison operators.

I'm writing this because I've seen a lot of comments that, while interesting in themselves, completely misunderstood the premise.

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

#136
One of the most intriguing novel ideas in Carbon (One of the "C++ Replacement languages" announced in 2022) is the idea that operator precedence should not be a total order.

Lots of prior languages have tried either:

1. No operator precedence, expressions must use parentheses so that it's very clear

2. No operator precedence, everything just happens left to right regardless

But Carbon says what if we do have precedence, but only between operators which programmers expect to have precedence - whenever it's unclear what should happen the compiler instead rejects that, the same way many languages won't let you ask whether 5 == "Five" because you need to explain WTF you intended as most likely you've screwed up and didn't realise they're completely different types.

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

#137

Please note that, despite the misleading title, TFA is about the precedence of bitwise operators & and | with respect to the comparison operators (== and all the others). In particular it was asked to Ritchie why the former are weaker than the latter in C, a rule generally considered a mistake because it makes it impossible to write common expressions like if (addr & mask == 0) without adding extra parentheses: if ((…

Thank you for this additional context.

So in short, bitwise operators have lower precedence than comparisons to allow you to write:

    if (a==b & c==d) ...
but of course, this means you can't write bitwise checks like this:

   if (addr & mask == 0) ...
The problem could theoretically have been solved when the shortcut operators were introduced, by increasing the precedence of & and | to be higher than comparisons, but have the shortcut operators be lower. So you would be able to write both:

   if (a==b && b==c) ...

   if (addr & mask == 0) ...
But this was not done due to concerns of backward compatibility with existing code, since now every expression using the old pattern would subtly change semantics. E.g. the first example would now be parsed as:

  if ((a==(b & c))==d) ...

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

#138
post #40

Unfortunately even though this was called out as a mistake in 1982, much more modern languages (e.g. C#) are still copying it. As painful as breaking changes might be, they beat the alternative of dealing with a bad design indefinitely. At least in more modern languages, the type checker usually catches the mistakes caused by this design mistake.

Python also fixed it.

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

#139
post #56

Earlier quoted context omitted.

I've never heard of saturation arithmetic and now it all makes sense. Otherwise I thought it was more common to think of XOR as boolean addition, and OR would be represented as xy + x + y.

Yes, true and false with AND and XOR form a mathematical ring [0]. Still, OR is also an additive operation. IMO one could give OR and XOR the same precedence. On the other hand, there is no strict need to have a dedicated boolean XOR operator, as it works the same as = (equals). [0] https://en.wikipedia.org/wiki/Ring_(mathematics)

More than just a ring, it is the simplest finite field.

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

#140
post #79

Earlier quoted context omitted.

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?

A + B + C is permitted in Ada.

https://learn.adacore.com/courses/Ada_For_The_CPP_Java_Devel...

Post reply on HN