I’m always suspicious of people who say that a language is suboptimal and use as evidence some filthy one-liner. Maybe if you bothered to write some whitespace and didn’t write the language ignorant of its features (like generator expressions) you would end up with better code?
sum( all( abs(x) >= 1 and abs(x) <= 3 for x in line ) and ( all(x > 0 for x in line) or all(x < 0 for x in line) ) for line in diffs )
You no longer have to “jump back and forth” except one single time - you have to look to the end to see where line
is coming from and then you can read the body of the main expression from start to finish.
People don’t, in fact, read code from top to bottom, left to right; they read it by first looking at its “skeleton” - functions, control flow, etc - until finding the bit they think is most important to read in detail. That implies that “jumping back and forth” is a natural and necessary part of reading (and hence writing) code, and so is nothing to fear.
There is still a slight advantage to not having to jump around, but consider the costs: in Javascript, map
and filter
are methods on Array
and some other types. So how are you going to implement them for your custom iterable type? Do you have to do it yourself, or write lots of boilerplate? It’s easy in Python. It’s not bad in Rust either because of traits, but what this all means is that to get this, you need other, heavy, language features.
In practice, you often know what a comprehension is iterating over due to context. In those situations, having what the comprehension produces be the most prominent is actually a boon. In these scenarios in Rust/JS you are left skipping over the unimportant stuff to get to what you actually want to read.
squaresinger@lemmy.world 3 days ago
I’m kinda surprised that pretty much nobody who commented here seems to have understood the point of the post.
It wasn’t about readability at all.
It was about designing APIs that the IDE can help you with.
With RTL syntax the IDE doesn’t know what you are talking about until the end of the line because the most important thing, the root object, the main context comes last. So you write your full statement and the IDE has no idea what you are on about, until you end at the very end of your statement.
Take a procedural-style statement:
len(str(myvar))
When you type it out, the IDE has no idea what you want to do, so it begins suggesting everything in the global namespace starting with l, and when you finish writing
len(
, all it can do is point out a syntax error for the rest of the line. Rinse and repeat for str and myvar.Object-oriented, the IDE can help out much more:
myvar.tostring().length()
With each dot the IDE knows what possible methods you cound mean, the autocomplete is much more focussed and after each
()
there are no open syntax errors and the IDE can verify that what you did was correct. And it you have a typo or reference a non-existing method it can instantly show you that instead having to wait until the end of the whole thing.