That is somewhat annoying, yes. I'm a huge fan of Python's list comprehension, but it's generally accepted to be a normal part of the language, and IMO, more readable:
print([x for x in range(10) if not x % 2])
[0, 2, 4, 6, 8]
vs.
l = []
for x in range(10):
if not x % 2:
l.append(x)
print(l)
[0, 2, 4, 6, 8]
I’m sure I’m biased, since I code mainly in Python. List/dict comprehensions read the same to me as the longer form, just more concisely. This can be taken too far, and you can wind up with horribly obtuse one-liners that are just awful.
I write and maintain code in a bunch of languages. Rust has risen to the first place, C is the close second followed by C++ and Python.
All of the languages except C have similar iterator-based stuff that let you write one liners and often with lambdas. I dislike them all. They give way too much leeway and encourage many developers to try to prove how clever they are.
Once you have to debug the code containing them, all of the complexity of the syntactic sugar comes crashing down on you. The debugger starts jumping to weird places, sometimes even optimized out parts of the standard libraries while for loops usually stay debugable.
I've seen people complain about wrapping a comprehension over multiple lines, but I can't imagine packing them all in one. In your example, I would spread it out over five lines, so it would be at as long as the imperative case.
While I like python, I think the unusual order that components of a comprehension are written is to its detriment. It would make more sense if they were in the same order in both examples. The python ternary has a similar issue.
Also not that the result is `[0, 2, 4, 6, 8, 10]`, unlike the behavior of Python which exclude the value explicitely passed in parameter from the represented range.