4 ms·
> Sometimes a programming design pattern becomes common enough to warrant its own special syntax. Python’s list comprehensions are a prime example of such a syn
by cballard 11y ago
> Sometimes a programming design pattern becomes common enough to warrant its own special syntax. Python’s list comprehensions are a prime example of such a syntactic sugar.
I disagree with this thesis, although the post is otherwise a very nice guide to list comprehensions. Special syntax for specific types indicates a failure of the language to be generic enough.
List comprehensions anoint lists as a special thing. You don't get to play with list comprehensions, unless you're using the type that the language has decided to let you play with. If you decide to use a different type for some reason, you... can't.
map and filter can be part of a typeclass/interface/protocol (in Python these would just be informal), so you can use them on arbitrary types. If you want to switch your list type, it should just work.
I write a lot of Swift, and I'm constantly frustrated that optional chaining (?.) and exceptions are special things. I can't implement ?. for my type (say, a Result). Only the language creators can use it. Somewhat confusingly, ?? is a thing I can implement.
In Python's case, I think that list comprehensions are necessary because the language's support for first-class closures is poor.
- leni536 11y ago> You don't get to play with list comprehensions, unless you're using the type that the language has decided to let you play with. If you decide to use a different type for some reason, you... can't. You can use generator expressions and pass it to your custom type's constructor. https://www.python.org/dev/peps/pep-0289/ https://www.python.org/dev/peps/pep-0289/
- sanderjd 11y agoYeah, it would be neater if they were just "iterable comprehensions" and worked with anything that is iterable.
- th 11y agoThat's kind of what generator expressions are actually :) https://www.python.org/dev/peps/pep-0289/ https://www.python.org/dev/peps/pep-0289/ You can pass them into anything that expects an iterable. That's pretty much the same since iterable types will frequently consume an iterable in their constructor. For example, here's a "tuple comprehension" (really just a generator expression passed to a tuple): >>> tuple(x for x in [1, 2, 3]) Same thing passed to list and set constructors (which you'd never do because we have the special comprehension syntax for those: >>> list(x for x in [1, 2, 3]) >>> set(x for x in [1, 2, 3]) I explained these in a very slightly different way in the linked webinar I linked in the post: https://youtu.be/u-mhKtC1Xh4?t=35m05s https://youtu.be/u-mhKtC1Xh4?t=35m05s
- icebraining 11y agoTo make it even more clear, you can store the generator in a variable and pass it around: >>> x = (a*a for a in range(3)) >>> type(x) <type 'generator'>
- Grue3 11y ago>Same thing passed to list and set constructors (which you'd never do because we have the special comprehension syntax for those I do this all the time (for set) because it works even in python 2.6. Also dict((key, value) for foo in bar). In fact, I think it was a bad idea to add special comprehension syntax for sets and dicts.
- sanderjd 11y agoExcellent. Mental model of what python can do: changed. I sort of thought that was a fancy python 3 feature, but looks like python 2 has it as well.
- dragonwriter 11y ago> List comprehensions anoint lists as a special thing. You don't get to play with list comprehensions, unless you're using the type that the language has decided to let you play with. That's one reason why I like Scala's comprehensions; they have the conciseness of list comprehensions, but are more generic.
- whateveracct 11y agoaka monads ;)