Earlier quoted context omitted.
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 defin…
Dennis Ritchie on the priorities of && || vs. == etc. (1982)
171–178 of 178 posts
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#172Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#173Earlier quoted context omitted.
I think equivalence and equality should different operators. 2==x should be a syntax error, because equivalence compares Boolean expressions (and possibly their extensions depending on the language). Equality should be checked with the customary sign, and assignment should be some visually asymmetric operator like :=. As you say, Equality should bind more strongly than the Boolean typed operations, including conjunct…
Sorry, I can't follow your reasoning. Probably I'm missing some basic vocabulary, because I don't appreciate the difference between equivalence and equality. Are we still talking about comparison operators?
Unless "equivalence" is supposed to be useful for comparing boolean expressions with unbound variables? But evaluating that would require a built-in SAT solver, to be remotely performant.
Also, just because two integers sum to 0 doesn't mean they're both equal to 0, so replacing (x == 0 && y == 0) with (x + y == 0) wouldn't be valid. Regardless, it wouldn't make for more performant code: compilers already translate (x == 0 && y == 0) into the assembly equivalent of ((x | y) == 0) automatically, without the programmer having to mess with their code.
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#174Earlier 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.
Parentheses need to be matched. That adds cognitive overhead. It's especially frustrating when you find the closing parenthesis and then realise it wasn't even necessary. IMHO it's on a similar level as "== true" "== false" and variations thereof --- absolutely redundant and unnecessary, and shows a lack of knowledge. The same "explicit is better than implicit" mantra is often repeated to justify the latter, but if y…
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#175Earlier quoted context omitted.
Sorry, I can't follow your reasoning. Probably I'm missing some basic vocabulary, because I don't appreciate the difference between equivalence and equality. Are we still talking about comparison operators?
I think GP is calling for == to only compare boolean values ("equivalence"), = to be necessary for comparing any other values ("equality"), and := to be used for assignment. Though I don't see the purpose in that, given that two boolean values are equal if and only if they are equivalent. Unless "equivalence" is supposed to be useful for comparing boolean expressions with unbound variables? But evaluating that would…
Indeed, I forgot to specify unsigned.
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#176Earlier quoted context omitted.
I think GP is calling for == to only compare boolean values ("equivalence"), = to be necessary for comparing any other values ("equality"), and := to be used for assignment. Though I don't see the purpose in that, given that two boolean values are equal if and only if they are equivalent. Unless "equivalence" is supposed to be useful for comparing boolean expressions with unbound variables? But evaluating that would…
> Also, just because two integers sum to 0 doesn't mean they're both equal to 0, so replacing (x == 0 && y == 0) with (x + y == 0) wouldn't be valid Indeed, I forgot to specify unsigned.
Unless the integers were unsigned big-integers, in which case performing the long addition with carries would take Θ(n) time, as opposed to the simple Θ(1) operation of just checking both their bit-lengths.
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#177Earlier quoted context omitted.
> Smalltalk [...] what r5rs Scheme should have been. I'm a fan of both languages, but R5RS Scheme was to be an algorithmic language, and Smalltalk is a particular flavor of OO language (class-instance, single dispatch). Would you say that doing conditionals and Boolean expressions with Smalltalk's object semantics and `ifTrue:ifFalse:` and mix of `and:` and `&` etc. is cleaner than Scheme's `if`, `and`, etc. syntax?…
By "should have been" I meant striking the balance of simplicity, power, and ease of learning that Smalltalk does. R5RS is simple and powerful (even more powerful due to macros), but not really usable, since it doesn't ship with something like Smalltalk's object model out-of-the box that streamlines creating ADTs and code reuse. Instead they give you the rudiments (functions, closures) and leave everything else up to…
SRFI-9 soon introduced a record type, and various Scheme implementations introduced much more.
Racket (nee MzScheme, or PLT Scheme) was one of them that introduced an object system, which was neat in some ways (e.g., mixins), but rougher in others, and thankfully it was limited to pedagogic and GUI use. There was also at least one CLOS-like. Later, Racket got a `struct` concept with some interesting hooks (e.g., inheritance/subtyping), and some simpler version of that might've been a good candidate for R5RS.
I'm don't know where RnRS is going recently, but I could imagine a fundamantal record/struct type, or interfaces more like the current Rust thinking.
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#178Earlier quoted context omitted.
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".
just a fun little anecdote. I wrote a piece of code that said ` if ( boolean_variable == true)` this was meant to be "if neither false nor null", since the variable was nullable (kotlin), until someone else tried to "fix the beginner mistake" :P luckily kotlin requires you handle the nullability and the other person immediately figured out what was going on. The other person was me, a couple of months down the line.