On Thu, Feb 15, 2018 at 10:13:37AM +0000, Jamie Willis wrote:
I'm not sure it does indicate a need for refactoring, I'd argue it's quite a common pattern, at least in functional languages from which this construct arises.
In fact, in those languages, there are laws that govern interactions with the comprehensions (though this comes from monads and monads perhaps don't quite apply to pythons model). These laws define behaviour that is expected equivalent by users;
Python is not a functional language, and the usual Pythonic solution to an overly complex or inefficient functional expression is to refactor into non-functional style. In my experience, most Python users have never even heard of monads, and those who have, few grok them. (I know I don't.)
[x for x in xs] = xs [f(x) for x in [x]] = f(x) [g(y) for y in [f(x) for x in xs]] = [g(y) for x in xs for y in f(x)]
I think these should be: [x for x in xs] = list(xs) # not to be confused with [x] [f(x) for x in [x]] = [f(x)] [g(y) for y in [f(x) for x in xs]] = [g(y) for x in xs for y in [f(x)]]
Even though that last law isn't completely analogous to the given example from the OP,
It can be used though. He has: [f(x) + g(f(x)) for x in xs] which can be written as [y + g(y) for x in xs for y in [f(x)]] Here's an example: # calls ord() twice for each x py> [ord(x) + ord(x)**2 for x in "abc"] [9506, 9702, 9900] # calls ord() once for each x py> [y + y**2 for x in "abc" for y in [ord(x)]] [9506, 9702, 9900] And one last version: py> [y + y**2 for y in [ord(x) for x in "abc"]] [9506, 9702, 9900] In production, I'd change the last example to use a generator comprehension.
the transformation he wants to be able to do does arise from the laws. So it could be argued that not being able to flatten the comprehension down via law 3 is unexpected behaviour
Law 3 does apply, and I'm not sure what you mean by the statement that we can't flatten the comprehension down. -- Steve