Hacker News new | past | comments | ask | show | jobs | submit login

> 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.




> 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/


> 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.


aka monads ;)


Yeah, it would be neater if they were just "iterable comprehensions" and worked with anything that is iterable.


That's kind of what generator expressions are actually :)

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


To 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'>


>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.


Excellent. 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.




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: