Hacker News new | ask | show | jobs
by frig 6036 days ago
I have a longer comment here that argues the opposite: list-comprehensions are only a syntactic pun or two away from set-builder notation, which is a higher level-of-abstraction (it declaratively states what it is) than map+filter (which specify a procedure to generate it, albeit at higher level of abstraction than a for-loop).

If you can put together a nontrivial usage of map+filter with at least three source collections that's more concise than the equivalent list comprehension I'll (figuratively) eat my hat.

2 comments

I'm not so sure if set notation is higher level, but for the example in your longer comment, map/filter/product is not that bad if you use it wisely. Here is my version:

    map(lambda (w,s,l): {'widget': w, 'sprocket': s, 'location': l}
        filter(lambda (w,s,l): l.hasInStock(w) and l.hasInStock(s) and w.isUsableWith(s), 
            product(widgets, sprockets, locations)))

Well, I agree it is not any conciser that its list comprehension (about the same I guess?). Nothing is perfect, like you said, know you tool :)
You'll be thrilled (lol) to know that the lambda-tuple syntax isn't in python 3 (!); it does make my examples more concise.

The argument in favor of set-notation being higher level is it's less specific (it doesn't explicitly provide a sequence of operations, just an outcome).

List comprehensions look like set notation but have an implicit procedural translation you have to keep in mind to use them well, so it's a toss-up.

I prefer map/filter/reduce when sequencing has large performance implications but for simple filtering or raw-data-shaping comprehensions read more smoothly.

http://books.google.com/books?id=RvY5BM0Xt1wC&lpg=PT367&...

> You'll be thrilled (lol) to know that the lambda-tuple syntax isn't in python 3

Now you know why many people like me are gradually pissed off by Python and start the exile ... currently trying Scala and it seems a nice language (with list comprehension too! :)

> List comprehensions look like set notation but have an implicit procedural translation you have to keep in mind to use them well, so it's a toss-up.

Actually I think that's the problem I have with list comprehensions: I use them a lot in my code, usually 1~3 levels nested and then have a hard time tracking down the order of implicit loops (which is inner vs outer) and make sure the intermediate variables (x for x in y for y in z ...) do not clash ... OK maybe I'm using it too much and in the wrong way :(

> I prefer map/filter/reduce when sequencing has large performance implications but for simple filtering or raw-data-shaping comprehensions read more smoothly.

I didn't know map/filter is faster than list comprehensions? I thought both are optimized by Python interpreter. But I like the idea of knowing that at least map can be parallelized easily. But since Python does not utilize multicore in a decent way, all bets are off :(

Using do-notation is probably cheating, but what do you think of this? (in Haskell):

  do { w <- widgets;
       s <- sprockets;
       l <- locations;
       guard (l `hasInStock` w);
       guard (l `hasInStock` s);
       guard (w `isUsableWith` s);
       return (w, s, l); }
We're trading horizontal space for vertical space. I think it's much clearer than either list comprehensions or plain map/filters. It's the best of both worlds.
I like the look of it. Am I correct that the order the statements are in translates into the order things are evaluated in when the code is called?

If eg I edited it to be:

    do { l <- locations;
         w <- widgets;
         guard (l `hasInStock` w);
         s <- sprockets;
         guard (l `hasInStock` s);
         guard (w `isUsableWith` s);
         return (w,s,l); }
Does that force it to go through "location-first" and only check the w and s of (w,s,l) for compatibility if it has already ascertained that w and s are in stock @ l?
Yes, that's correct.