Re: [Python-ideas] Assignments in list/generator expressions
In a message of Sun, 10 Apr 2011 09:31:53 EDT, Eugene Toder writes:
It isn't strangely missing at all, it's just hard: http://www.python.org/dev/peps/pep-3150/
Local definition in list comprehension is significantly simpler that 'given'. Semantically, 'with name = expr' can be treated as a more readable form of 'for name in [expr]'. Implementation can use a simple assignment.
Eugene
We'll have to disagree then. I think 'for name in [expr]' is a whole lot more readable than 'with name = expr'. Indeed, my recent experience in code reading had shown, I thought, that a good number of people are using the with statement whenever they possibly can, to the detriment of readability. Comments like this make me wonder if the problem is that those people actually find those constructs more readable. If we largely cannot agree on what makes for more readable code, then I think we have a different problem than the one I thought we had (people showing off their knowledge of how to use every new feature). Laura
On Mon, Apr 11, 2011 at 1:13 AM, Laura Creighton <lac@openend.se> wrote:
Comments like this make me wonder if the problem is that those people actually find those constructs more readable. If we largely cannot agree on what makes for more readable code, then I think we have a different problem than the one I thought we had (people showing off their knowledge of how to use every new feature).
I don't think it's an either/or problem - I think both of those things can cause problems with code readability. One of the first questions I want to ask people that try to push Python's comprehension syntax to (and past) its limits is whether they have come to Python programming from a mathematics or pure functional programming background. If they have, then "normal" imperative programming will feel understandably unnatural to them, despite it being the idiomatic approach to Python programming (with comprehensions only being employed for those relatively simple cases they were really designed to handle). But I also see people using metaclasses for things that should be decorators, context managers for things that should be ordinary higher order functions, higher order functions for things that should just be plain boring old functions, closures for things that should be classes... all of those I tend to chalk up to "when you have just discovered a nice shiny new hammer, everything looks like a nail (even when you still have the saw, screwdriver and pliers in the toolkit)". Or, as I once heard it put, some code overuses powerful constructs to the point where it is like "using a bazooka to kill a fly" :) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
We'll have to disagree then. I think 'for name in [expr]' is a whole lot more readable than 'with name = expr'. Indeed, my recent experience in code reading had shown, I thought, that a good number of people are using the with statement
It's well known that minor syntax details cause a lot of disagreement (http://www.haskell.org/haskellwiki/Wadlers_Law), so that's not very surprising. However, are you sure you're not confusing python's with statement and 'with' word in my email, which is simply a placeholder for appropriate keyword to mirror Haskell's 'let'? Or was this just an occasion to complain about with statement abuse, unrelated to list comprehension discussion? If I was not clear: I used 'with' keyword for demonstration purposes only, to show what the syntax *might* look like. I do not suggest to reuse 'with' (even though python has a history keywords reuse, e.g. 'else'), it's just a placeholder.
While naming the iteration variables is a fundamental part of writing comprehensions, naming other subexpressions is not, so it doesn't make sense to provide comprehension specific syntax for it.
Well, apparently designers of Haskell, Scala, F# and Clojure decided that it does make sense to provide a comprehension specific syntax for naming subexpressions in comprehensions. Eugene
On Sun, Apr 10, 2011 at 11:31 AM, Eugene Toder <eltoder@gmail.com> wrote:
We'll have to disagree then. I think 'for name in [expr]' is a whole lot more readable than 'with name = expr'. Indeed, my recent experience in code reading had shown, I thought, that a good number of people are using the with statement
Eugene, I'm pretty sure you didn't write that, but as I'm not following this megathread in real time I don't know who did. Can you please be so kind to leave attributions in? (I'm glad you snip stuff you don't need, but the attributions are essential.)
If I was not clear: I used 'with' keyword for demonstration purposes only, to show what the syntax *might* look like. I do not suggest to reuse 'with' (even though python has a history keywords reuse, e.g. 'else'), it's just a placeholder.
It was not clear.
While naming the iteration variables is a fundamental part of writing comprehensions, naming other subexpressions is not, so it doesn't make sense to provide comprehension specific syntax for it.
Well, apparently designers of Haskell, Scala, F# and Clojure decided that it does make sense to provide a comprehension specific syntax for naming subexpressions in comprehensions.
If the designers of Haskell, Scala, F# and Clojure jumped off a cliff, would you jump too? :-) Those languages are all considerably more "functional" in nature than Python will ever be. It's hard to express Python's design principles exactly, but "following other languages" has never been high on the list. We do borrow good ideas, but tend to reinterpret them in the context of Python's existing semantics, syntax and constraints. We also place a high value on growing the language very slowly and carefully; too many shiny new features are more likely to distract than to help, even if each one individually is a great idea. And we have a history of stuff we do and don't like, which may not always be rational, but which has served us well up to here. If you don't like it, you can always write one of those other languages... (That's not to say that I am vetoing a specific proposal. But the bar is high, and inventing a "Pythonic" syntax is a prerequisite. So is a good story with a set of examples explaining why the new feature adds something you cannot easily do today.) -- --Guido van Rossum (python.org/~guido)
On Sun, Apr 10, 2011 at 7:06 PM, Guido van Rossum <guido@python.org> wrote:
Can you please be so kind to leave attributions in? (I'm glad you snip stuff you don't need, but the attributions are essential.)
<snip>
It was not clear.
Will try to improve on both accounts. On Sun, Apr 10, 2011 at 7:06 PM, Guido van Rossum <guido@python.org> wrote:
(That's not to say that I am vetoing a specific proposal. But the bar is high, and inventing a "Pythonic" syntax is a prerequisite. So is a good story with a set of examples explaining why the new feature adds something you cannot easily do today.)
This particular feature is not the top on my wish list either. I just don't see a good explanation for why it's missing. It's a lesser-known feature in Haskell (no mention in Wikipedia! :-), but it is handy at times. As mentioned above, people suggest it for Python from time to time. As for the syntax, there are many choices. Going with <keyword> name = expr, <keyword> can be 'let', as in Haskell, F# and Clojure, or 'where' as Greg suggested above, or 'given' as it's related to PEP 3150 -- the scope of name partially extends to the left of it's definition. From the backward compatibility point, 'let' is likely too short for a new keyword, and PEP 3150 describes the problem with 'where'. ys = [y for x in xs where y = f(x) if y] ys = [y for x in xs given y = f(x) if y] There are likely other words that will do. Alternatively, some punctuation can be used, e.g. semicolon: ys = [y for x in xs; y = f(x) if y] Eugene
On Sun, 2011-04-10 at 20:18 -0400, Eugene Toder wrote:
On Sun, Apr 10, 2011 at 7:06 PM, Guido van Rossum <guido@python.org> wrote:
Can you please be so kind to leave attributions in? (I'm glad you snip stuff you don't need, but the attributions are essential.)
<snip>
It was not clear.
Will try to improve on both accounts.
On Sun, Apr 10, 2011 at 7:06 PM, Guido van Rossum <guido@python.org> wrote:
(That's not to say that I am vetoing a specific proposal. But the bar is high, and inventing a "Pythonic" syntax is a prerequisite. So is a good story with a set of examples explaining why the new feature adds something you cannot easily do today.)
This particular feature is not the top on my wish list either. I just don't see a good explanation for why it's missing. It's a lesser-known feature in Haskell (no mention in Wikipedia! :-), but it is handy at times. As mentioned above, people suggest it for Python from time to time.
As for the syntax, there are many choices. Going with <keyword> name = expr, <keyword> can be 'let', as in Haskell, F# and Clojure, or 'where' as Greg suggested above, or 'given' as it's related to PEP 3150 -- the scope of name partially extends to the left of it's definition. From the backward compatibility point, 'let' is likely too short for a new keyword, and PEP 3150 describes the problem with 'where'.
ys = [y for x in xs where y = f(x) if y]
ys = [y for x in xs given y = f(x) if y]
There are likely other words that will do. Alternatively, some punctuation can be used, e.g. semicolon:
ys = [y for x in xs; y = f(x) if y]
Eugene
Semi-colon is already in use and to me (perhaps because of C) tells me they are unrelated statements. where to me seems the more Pythonic.
On Mon, Apr 11, 2011 at 12:10 AM, Westley Martínez <anikom15@gmail.com> wrote:
Semi-colon is already in use and to me (perhaps because of C) tells me they are unrelated statements. where to me seems the more Pythonic.
Right, keyword is definitely more Pythonic. The problem with 'where' is that it's already used as identifier by various SQL frameworks, which is why PEP 3150 uses 'given' instead. Eugene
Eugene Toder wrote:
The problem with 'where' is that it's already used as identifier by various SQL frameworks, which is why PEP 3150 uses 'given' instead.
That's not necessarily a deal-breaker -- it could be made context-sensitive, like was done with 'as' for a few versions before it became a true keyword. -- Greg
On Tue, Apr 12, 2011 at 9:24 AM, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
Eugene Toder wrote:
The problem with 'where' is that it's already used as identifier by various SQL frameworks, which is why PEP 3150 uses 'given' instead.
That's not necessarily a deal-breaker -- it could be made context-sensitive, like was done with 'as' for a few versions before it became a true keyword.
Eugene slightly mischaracterised the objection I have to the choice of "where" as the keyword in the context of PEP 3150. It isn't that it breaks existing libraries, it breaks database programmers' *brains*, because "where" is the SQL keyword for filtering. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
Nick Coghlan wrote:
It isn't that it breaks existing libraries, it breaks database programmers' *brains*, because "where" is the SQL keyword for filtering.
The SQL usage is a special case of the more general way it's used in mathematics. I don't think database programmers can expect to hijack the term and force everyone else to follow their own particular interpretation of it. -- Greg
I wrote:
I don't think database programmers can expect to hijack the term and force everyone else to follow their own particular interpretation of it.
Having said that, I'm starting to think that 'given' works better the way PEP 3150 uses it, when the block contains things other than assignments. Somehow 'where def f' doesn't sound right, but 'given def f' does. -- Greg
On Tue, Apr 12, 2011 at 10:10 AM, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
The SQL usage is a special case of the more general way it's used in mathematics. I don't think database programmers can expect to hijack the term and force everyone else to follow their own particular interpretation of it.
The database programmers aren't forcing anyone to do anything. While I don't have formal survey data to back it up, I'm reasonably confident in stating that if you grab a random Python programmer and ask them how they understand the term "where clause", it'll be something like: - mostly blank looks - many responses along the lines of the way SQL uses it - a vanishingly small minority that are consciously aware of the formal mathematical usage (and the way it relates to English usage of the word) Programming may have its origins in computer science, which in turn has its origins in mathematics, but my personal experience is that very few day-to-day programmers have actually had sufficient exposure to formal mathematical terminology for it to come to mind before the SQL use case. Now, that personal experience is biased towards an engineering environment, but I'd consider that more representative of the wider industry than a university environment. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
Laura Creighton wrote:
We'll have to disagree then. I think 'for name in [expr]' is a whole lot more readable than 'with name = expr'.
I think I would find 'where name = expr' slightly more readable and aesthetically pleasing than either 'with name = expr' or 'for name in [expr]'. However if 'for name in [expr]' were optimised to use an assignment instead of a for-loop, I might consider using it more often. Currently I would be reluctant to do so because it feels so inefficient. -- Greg
participants (6)
-
Eugene Toder
-
Greg Ewing
-
Guido van Rossum
-
Laura Creighton
-
Nick Coghlan
-
Westley Martínez