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...
Dennis Ritchie on the priorities of && || vs. == etc. (1982)
121–130 of 178 posts
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#122Earlier quoted context omitted.
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 a…
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#123I 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).
The array language people (APL, J, K) are going to come in and protest, but you aren't going to be able to understand them.
/s
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#124I 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.
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.
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#125Earlier quoted context omitted.
Consider (&& a b) and (|| a b) for no uncertainty over operator precedence and easy variadic representation (&& a b c) at the cost of zero additional parentheses.
While true and might be easy to read in the example context of a b c I'd imagine having the && separator in real world conditions to be far more readable and clear for vast majority if people
if (a != null && x != 0 && a.use_it(x))
{
...
}
(if (and (not (null a))
(/= 0 x)
(use-it a x))
...)Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#126Earlier 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.
(isAdmin || (canReadDocument && canModifyMetadata)) && accountIsActive
Using parentheses makes the code a lot easier to understand here. All these variables carry state with lots of subtleties. Figuring out the implications of all the different cases becomes a lot easier when the code clearly tells them apart.
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#127Earlier quoted context omitted.
> except in broken languages, of which the only notable one is shell All binary messages in Smalltalk (messages with selectors consisting of punctuation, like !@+-, including punctuation sequences like "+-&|", if you want) have the same precedence, and the keyword variants (which short-circuit, using block arguments) and: and or: also have the same precedence (one level lower than the binary/punctuation messages), bu…
> 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?…
> We were very pleased with this toy actor implementation and named it “Schemer” because we thought it might become another AI language in the tradition of Planner and Conniver. However, the ITS operating system had a 6-character limitation on file names and so the name was truncated to simply SCHEME and that name stuck. (Yes, the names “Planner” and “Conniver” also have more than six characters. Under ITS, their names were abbreviated to PLNR and CNVR. We can no longer remember why we chose SCHEME rather than SCHMR—maybe it just looked nicer.)
> then came a crucial discovery. Once we got the interpreter working correctly and had played with it for a while, writing small actors programs, we were astonished to discover that the program fragments in apply that implemented function application and actor invocation were identical! Further inspection of other parts of the interpreter, such as the code for creating functions and actors, confirmed this insight: the fact that functions were intended to return values and actors were not made no difference anywhere in their implementation. The difference lay purely in the primitives used in their bodies. If the underlying primitives all returned values, then the user could (and must) write functions that return values; if all primitives expected continuations, then the user could (and must) write actors. Our interpreter provided both kinds of primitives, so it was possible to mix the two styles, which was our original objective.
> But the lambda and alpha mechanisms were themselves absolutely identical. We concluded that actors and closures were effectively the same concept.
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#128Earlier quoted context omitted.
Is there an intuition for this correspondence otherwise I don't think it's very helpful
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…
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#129I don't know if the following addendum is apocryphal or not, but I still like it.
Follow-up question: several hundred kilobytes? Why didn't you just grep for all instances of "&"?
Dennis Ritchie: because that happened in 1972, and Ken would write grep only in 1973.
Re: Dennis Ritchie on the priorities of && || vs. == etc. (1982)
#130I 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.
Early in my career I erased several megabytes of shared memory on a mini computer, ie DOZENS of users worth of memory just because I was being 'clever' and cut+pasted bits of an expression the wrong way.
Since then, as a rule, sod the priorities, parenthesis it is...