Live data from Hacker News

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

lysator.liu.se

111–120 of 178 posts

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

#111
post #94

Earlier quoted context omitted.

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.

Most people might agree with that, I don't know, but I know I don't think your first example is clearer. And I've had the operator precedence rules memorized for decades. Parentheses save my brain a step. The second example is irrelevant because addition is commutative so the parentheses are meaningless. (This is why languages shouldn't override + to be a concatenation operator.)

The important part that makes the parens in the second operation unnecessary is that addition is associative, not that it's commutative. And concatentation is also associative, so even if those were strings, the parens would still be unnecessary.

That is, (a+b)+c == a+(b+c).

Interestingly, C integer addition is not actually associative, since (1+INT_MAX) + (-1) is UB, but 1+(INT_MAX+(-1)) should in principle be defined as INT_MAX.

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

#112
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…

because 1 \and 0 = 0 same as 1 * 0 = 0 and 1 \or 0 = 1 same as 1 + 0 = 1

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

#113

Earlier quoted context omitted.

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…

because 1 \and 0 = 0 same as 1 * 0 = 0 and 1 \or 0 = 1 same as 1 + 0 = 1

Choosing false = 0 and true = 1 is putting the cart before the horse.

It is equally true that 1*0=0 is the same as false|true=true, and 0+1=1 is the same as true&false=false.

But it is also not true that 1+1=1, so it is probably wrong to equate 'or' with '+'. The operation has the wrong properties.

As someone who sometimes dabbles in electronics, 0 = true makes a lot of intuitive sense to me. You have your pin with an open collector, your pull-up resistor, and “true” (as in, it is true that the transistor is conducting) pulls the voltage to ground, which is 0.

As someone who uses a Unix shell, 0 = true makes a lot of intuitive sense to me.

  $ true; echo $?
  0
  $ false; echo $?
  1

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

#114

There's a niche language called Sail that has & and | act as both bitwise and boolean operators. It actually works really well and isn't confusing at all after the initial "this is different". There's no real downside because it is a modern strictly typed language unlike C. On the other hand I don't know if there's a real upside either. It's not very difficult to use && and || and it serves as extra documentation, an…

Forths often use -1 as TRUE so logical and bitwise operators coincide.

So did BASIC traditionally, with no short-circuiting behavior AFAIK. At least Visual Basic has `AndAlso` and `OrElse` variants that do short-circuit though.

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

#115

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 just asked myself the question for SQL's AND and OR this week. Apparently AND takes precedence but I don't know if it is consistent accross all SQL engines. In any case it seems to me that few programers will know anyway, so it is bad practice to not have parenthesis.

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

#116

Earlier quoted context omitted.

Wrong. In C and C++, == has a higher precedence than && and ||, so `A && B == C && D` parses as `A && (B == C) && D`.

== is really just a logical xor anyway.

You mean "xnor", right? It's the != operator which corresponds to xor.

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

#117
post #46

Earlier quoted context omitted.

"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'.

Something nice in C is that "if (x)" is always equivalent to "if (x != 0)". NULL is a macro for 0, and so is false. Boolean expressions evaluate to 0 if they don't hold. This isn't true in C++, though.

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

#118
post #49

There's a niche language called Sail that has & and | act as both bitwise and boolean operators. It actually works really well and isn't confusing at all after the initial "this is different". There's no real downside because it is a modern strictly typed language unlike C. On the other hand I don't know if there's a real upside either. It's not very difficult to use && and || and it serves as extra documentation, an…

I'm not familiar with Sail, but the reason for separate logical operators is that you want short-circuiting behavior. For example, in: (a != NULL) && a->x You don't want to right-hand side to be evaluated if the left-hand side is false.

It does short circuit if the parameters are booleans.

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

#119
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?

Yeah. To sum two bits x and y, the immediate sum is x XOR y, and the carry is x AND y. That's how a simple half-adder circuit can be made.

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

#120

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.

Do you know the priority in this? [ -e "${target}" ] && echo "Getting information about ${target}" && stat "${target}" || echo "Failed to stat file." EDIT: What about the || die("...") pattern in Perl? Or the fact that the glyphs in || are visually lower than the glyphs in &&? Or that "and" comes before "or" in the expression "and/or"?

The shell command is very readable.

a && b && c is a common idiom for "stop if any step fails". In the shell language && and || are more like control flow concepts, rather than binary operators.

And a && b || c is a universal "ternary operator" (with one minor deviation) idiom across many languages, not just the shell

Post reply on HN