On Mon, 22 Jun 2009 08:40:05 pm Nick Coghlan wrote:
Lambdas, comprehensions and expressions in general all have limits - usually deliberate ones. When one runs up against those limits it is a hint that it is time to switch to using multiple statements (typically factored out into a function that can be substituted for the original inline expression)
But then, I'll freely confess to not really understanding the apparently common obsession with wanting to be able to do everything as an expression.
Some things are conceptually a single operation, and those things are good to write as a single expression. Before we had sorted(), it was uncomfortable to write:
L.sort() return L
when you wanted a sorted list, because "return a sorted list" is conceptually a single operation, even if sorting is non-trivial. The solution to this was to write a helper function, which was made obsolete when sorted() became a built-in.
The OP's suggestion:
[(f(x), f(x)) for x in some_iterable if f(x) < 2]
is not conceptually a single operation, because producing a list of two-tuples containing some value y repeated but only if y is less than 2 is not conceptually simple. If it were, it would be easy to describe the operation with one or two words, instead of the fourteen it took me.
I still believe that the right way to solve this is with a pipeline of simple operations:
map(lambda obj: (obj, obj), filter(lambda y: y < 2, map(f, some_iterable)))
Re-write with temporary variables, itertools, and generator expressions as preferred.