It's interesting that the comparator function is one of the examples, because that's something which shows how people often confuse verbose with clear ; I think it's best written in a single line: return a b ? 1 : 0; That's one line, compared with the 10(!) of his proposed method using a switch statement. Having worked with some "modern" codebases, I think verbosity is a bigger problem that's become especially preval…
Clear is better than clever [pdf]
251–260 of 335 posts
Re: Clear is better than clever [pdf]
#252It's interesting that the comparator function is one of the examples, because that's something which shows how people often confuse verbose with clear ; I think it's best written in a single line: return a b ? 1 : 0; That's one line, compared with the 10(!) of his proposed method using a switch statement. Having worked with some "modern" codebases, I think verbosity is a bigger problem that's become especially preval…
It's not 10 lines, it's 8. Your implementation would need the function declaration and the } at the end too. Now consider this: return a > b ? 1 : a Or: return a == b ? 0 : a Or: return b Are all these equivalent? Figuring that out is much more difficult than their 8-line counterpart, at least for me. My eyes have to keep jumping from left to right in order to do the checks, like they would do in a piece of uglyfied…
But is that really what you're looking for? I see that idiom and I think, "Ok, this is a comparator" and I move on. If I suspect a _bug_ in the comparator, then I'll look at it more carefully, but the context is about writing code whose intent is clear, not writing code that can be scanned for bugs easily - which would be a tall to impossible order anyway and isn't made any easier by sprawling your code across 10 lines where one will do.
Re: Clear is better than clever [pdf]
#253It's interesting that the comparator function is one of the examples, because that's something which shows how people often confuse verbose with clear ; I think it's best written in a single line: return a b ? 1 : 0; That's one line, compared with the 10(!) of his proposed method using a switch statement. Having worked with some "modern" codebases, I think verbosity is a bigger problem that's become especially preval…
Why not something as simple as `return (a - b)` ? It’s concise and simple to understand. Instead of returning 1 or -1 it returns a positive or negative value with I think is equally effective.
That will overflow if a & b are longs.
Re: Clear is better than clever [pdf]
#254> To be clear, I don’t mean to dismiss the work of a lone programmer toiling on programs without anyone to pair with or learn from. I’ve been that person many times in my career as a programmer, it’s not fun. I'd say it's a lot of fun.
Re: Clear is better than clever [pdf]
#255This is my mantra for JavaScript. So much of the post ES6 code I see seems more clever than clear.
Re: Clear is better than clever [pdf]
#256Earlier quoted context omitted.
If/else chains are worse because they allow problems like this: if (cond) { var1 = x; } else if (cond2) { var2 = y; } else { var1 = z; } Did you notice the second block assigned to var2 instead of var1? Best case it’s a gotcha for anyone reading the code later. It might be a bug by the original author; we can’t tell at a glance if this behaviour was intentional. Ternaries remove this problem. The intent of the author…
If I understand correctly, what you're really advocating isn't ternary vs if/else, but expressive conditionals vs imperative conditionals. A statement that is something vs a statement that does something. Using expressions instead of imperative code that mutates state is a staple of functional programming, and is basically always preferred where possible. In some languages you can do this: var1 = if cond { x } else i…
My favorite part is that its easy to add extra statements into the conditional blocks if you want. Doing that with ternaries requires either using the comma operator, repeating the condition on another line or refactoring the whole expression back out into if-else chains. All of those options are bad.
Re: Clear is better than clever [pdf]
#257Earlier quoted context omitted.
Nested ternary is obvious when formatted as above, and it's dramatically more compact. Try it for a bit, you'll see how simple and clear it is.
You see the problem though, I need to try it and practice it to see how simple and clear it is. I can write code that I can easily understand. I can write terse, clever code that I can easily understand. But I want to write code so that the next person can also easily understand it. More importantly, code that's easier to understand has less chance of getting buggy when it inevitably gets rfactored or extended. >and…
You need to practice it to overcome your skepticism resulting from your ingrained habits that prejudice you against it, not because it's inherently unreadable. It literally takes 5 seconds to understand the idiom: conditions/guards on the left, value on the right. It's essentially a truth table.
> Why do I want that?
To add to the other poster: the more context you can fit on your screen, the less scrolling, jumping you need to do to understand a program's behaviour. Compactness that doesn't sacrifice readability speaks for itself. The code sample we're discussing is compact and very readable.
Re: Clear is better than clever [pdf]
#258Earlier quoted context omitted.
On the contrary, I think the zeitgeist for the last 5-10ish years has been the opposite. "Verbose and explicit > Succinct and implicit". I think python and golang are largely responsible for this kind of movement in recent years. Because of that, I find languages like Perl 6 to be a breath of fresh air.
That's interesting. I wonder if that's influenced by the languages we use, as they might have different cultures. I primarily work in Java, which is famously verbose.
For example, there’s a big thread about the three-way comparison function in this discussion. Lots of people don’t like nesting ?: syntax to implement the required behaviour as a one-liner, but the objections essentially seem to be about the syntax of the ternary-if operator in C family languages. In another language, with a more intuitive syntax for this behaviour that doesn’t look like operator soup, the underlying idea of testing a series of conditions in order and yielding a single output value based on the first condition that matches might be perfectly intuitive to those same people.
Someone else in that thread commented that using a switch statement with conditions rather than specific values was unwelcome because then the more general conditions might overlap. Again, that view seems to be based on what the keyword “switch” means in a lot of established programming languages. There are other languages with features that test a series of potentially overlapping conditions in order and act based on the first match, and perhaps that same person might not have had the same objection to the same behaviour if it didn’t come with the baggage of the term “switch”.
At this point, I personally wish I could concentrate more on the intent when I’m programming. For example, do we need an expression or a statement here, or are our conditions a set of mutually exclusive options or potentially overlapping? My ideal programming language today would provide ways to express differing intents with some — any — reasonable syntax, but with very clearly defined semantics. Whether a language uses semicolons or syntactic whitespace or Lispy parentheses has long since stopped mattering to me. But that’s the me who’s been doing this for a long time and got tired of debates about minor details because in the end they mostly don’t matter. A younger me, one in the early years of his programming adventures who hadn’t yet seen these discussions a hundred times before and didn’t yet think in the same ways, would probably have delighted in the language lawyering and syntactic quibbles in that thread, and would no doubt have had a strong opinion on each suggestion.
And that brings us neatly back to where we came in, because it means the properties of code that is clear and desirable to me today are very different to the properties that would have made code clear and desirable to me, say, twenty years ago. So if I were writing code today and trying to be as clear as possible, my target audience would be a huge factor in the choices I’d make.
Re: Clear is better than clever [pdf]
#259Earlier quoted context omitted.
This is a beautiful way to express multiple ?: expressions.
I don't agree. It occludes the nested structure. We can regard the condition as the head of a clause, and the ? and : as heads of sub-clauses: A ? B : C which leads to: return a b ? 1 : 0;
The nesting is irrelevant to understanding the semantics, so this objection doesn't fly. The idiom is basically just a truth table with conditions on the left and the matching value on the right. You read it left-to-right, top-to-bottom, just like all other code. The first condition on the left that matches returns the value on right-hand side.
Re: Clear is better than clever [pdf]
#260Earlier quoted context omitted.
My favourite solution to this problem is how rust does it. In rust every block can evaluate to an expression, so if/else is the ternary operator. let x = if cond1 { expr1 } else if cond2 && cond3 { expr2 } else { expr3 }; It’s more verbose this way (‘?’ Vs ‘else if’) but there’s no question of readability because it’s just if/else. You can format it however you like, and add statements into the blocks later if you ne…
Very lispy :-) Some would say top-level blocks returning the last value in the block is an anti-pattern, because functions which aren't meant to return a value end up leaking the value of the last thing called in the function, which might be another function, which called another function. Or it might be in various branches of an 'if', which aren't being examined for being an acceptable return value. Perl does this,…
Rust will also only return the last expression in a block if it doesn't end in a semicolon. This can be a bit subtle when you're reading a long function, but combined with explicitly specified return types its hard to mess up while writing code. Because of the choice about that semicolon, its an explicit choice whether you want a block to evaluate into that expression or not. And for functions you can always just use an explicit return statement if you want anyway.