I'm a Python fan but I can't disagree more on that point. Python has terrible lambdas, and poor idioms when working with collections (list iteration over chainable/fluid interfaces).
Underscore.js, which at this point stands for 'idiomatic JS for collections', and the ES5 methods on arrays (filter/map) which are largely supported now provide a better way to handle arrays & hashes than idiomatic Python. With ES6 fat-arrow functions it's even better.
It's one of Python's biggest weaknesses when compared to other dynamic languages IMO -- that the idiomatic way to deal with 'collections' is not a chainable/fluid pattern, but instead to do multiple list comprehensions, or use the ugly filter-plus-lambda patterns which compose badly.
Double evens in a list:
ES6:
[1, 2, 3]
.filter(x => x % 2 == 0)
.map(x => x * 2)
ES5: [1, 2, 3]
.filter(function(x) { return x % 2 == 0 })
.map(function(x) { return x * 2 })
Python: map(lambda x: x * 2,
filter(lambda x: x % 2 == 0, [1, 2, 3]))
# or
evens = [x for x in [1, 2, 3] if x % 2 == 0]
[x*2 for x in evens]
The ES6 & ES5 JS examples are both clearly superior syntax IMO. More readable and the anonymous functions support multi-line so extend to more use-cases.EDIT: Removed the word 'objective' because I'm talking syntax.
map(lambda x: x * 2,
filter(lambda x: x % 2 == 0, [1, 2, 3]))
But the list comprehension version is just completely wrong: [x*2 for x in [1, 2, 3] if x % 2 == 0]
Which, in our subjective world, is cleaner than the ES5 version and almost as clean as the ES6 version.I was not trying to illustrate that the backslash made it ugly (I've removed it - I was pasting from a repl). It's ugly because of Python's lambda syntax and the fact it does not compose 'sensibly', as compared to fluid interfaces. The logic is back-to-front for one.
> But the list comprehension version is just completely wrong:
No, it's not at all wrong. Your one-liner is not better and (I hope) would probably upset most teams for being less clear.
I was providing a like-for-like example. The multi-lining is not the criticism of the Python version. It's the composition that's at fault, the fact it does not feel like 'two coherent operations over a list' with two distinct conditionals.
The ES5/ES6 examples demonstrate this much more clearly IMO.
Presumably, these also are not completely clear to you:
> [x * 2 | x <- [1, 2, 3, 4], even x]
[4,8]
> [x * 2 | x <- filter even [1, 2, 3, 4]]
[4,8]
What, exactly, is not clear here? This is the essence of composition; to use clearly defined things together. I can appreciate a good pipeline as much as the next guy, but to say that this is somehow more complicated and hard to read is to overstretch a little bit.To say that a pretty uncluttered list comprehension is some challenge to read is just hyperbolic. These pipelines, even with newlines, can get pretty long and terrible too.
This sentence reveals a deep misunderstand of either what "objectively" means.
(FWIW, I prefer the ES5/ES6 syntax to Python here, as well; I just don't mistake that preference for something other than subjective.)
It's easy to pedantically point out I used 'opinion' in the same sentence as 'objective' but I'd hope you could apply 'the context of programming' to gather what I actually meant.
When we say 'objective' over matters of syntax I tend to think of 'If you put N programmers in a room they'd all agree this was better syntax'. That's how I feel about the above examples I posted.
That said I've edited my comment so I don't inflame other commenters to point out my glaring contradiction :)
I like Javascript, in many ways it's a neat little language, but manipulating the small little ad-hoc data structures (arrays and hashes, and combinations of them) that seems to be half of most programming tasks is definitely a step backwards compared to Python.