_______________________________________________This syntax basically allows to put any code from functions into comprehensions. This enables people to write fewer functions at the cost of more complex comprehensions. But functions are a good idea indeed:
* They have a name and from that name it should be clear what that function does without having to look at the implementation.
* Functions can have documentation to provide more information about their behaviour.
* Functions have meaningful arguments possibly with type annotations that make it clear what input and output of that operation is.
* Functions can be reused.
* Functions can be tested.
With that extended comprehension syntax you'll loose all of the above benefits. Since people can put arbitrary complex code into the comprehensions this puts a burden at whoever has to read the code.
As for your first example this is already possible via
[stripped for line in lines if (stripped := line.strip())]
The matrix example is already pretty complex, and the comprehension difficult to read.
Plus for simple comprehensions you have now to ways to write them:
[f(x) for x in stuff]
[for x in stuff: f(x)]
I think the first version is much better because you can see immediately what the resulting list contains: f(x) objects. In the second version you have to reach the end of the comprehension to get that information and the `for x in` part is not really interesting.On 2/21/20, 14:49 Alex Hall <alex.mojaki@gmail.com> wrote:> Yes but then it's the same as defining a generator-function.
List comprehensions are already the same as other things, but they're nice anyway. `lambda` is the same as defining a function, but it's nice too. Syntactic sugar is helpful sometimes. I think this:
clean = [
for line in lines:
stripped = line.strip()
if stripped:
yield stripped
]
is easily nicer than this:
def clean_lines():
for line in lines:
line = line.strip()
if line:
yield line
clean = list(clean_lines())
And this:
new_matrix = [
for row in matrix: yield [
for cell in row:
try:
yield f(cell)
except ValueError:
yield 0
]
]
is nicer than any of these:
new_matrix = []
for row in matrix:
def new_row():
for cell in row:
try:
yield f(cell)
except ValueError:
yield 0
new_matrix.append(list(new_row()))
----
def new_row(row):
for cell in row:
try:
yield f(cell)
except ValueError:
yield 0
new_matrix = [list(new_row(row)) for row in matrix]
----
def safe_f(cell):
try:
return f(cell)
except ValueError:
return 0
new_matrix = [
[
safe_f(cell)
for cell in row
]
for row in matrix
]
> > I think it's ambiguous, like in this example:
> clean = [
> for line in lines:
> stripped = line.strip()
> if stripped:
> stripped
> ]
> what says that it's the last stripped that should be yielded?
Because it's the only statement that *can* be yielded. The `yield` is implicit when there's exactly one statement you can put it in front of. You can't `yield stripped = line.strip()`. You can technically have `stripped = yield line.strip()` but we ignore those possibilities.
> > If that function is the whole statement and there is
> > no other expression statement in the comprehension, it will be yielded. I can't tell if
> > there's more to your question.
> > Imagine this one:
> foo = [
> for x in range(5):
> f(x)
> if x % 2:
> x
> ]
> what will be the result?
It will be a SyntaxError, because it's ambiguous.
Here's a new idea: `yield` is only optional in inline comprehensions, i.e. where the loop body consists entirely of a single expression. So for example this is allowed:
new_row = [for cell in row: f(cell)]
but this is not:
new_row = [
for cell in row:
thing = g(cell)
f(thing)
]
Instead the user must write `yield f(thing)` at the end.
This would mean that you only need to add `yield` when the comprehension is already somewhat long so it's less significant, and there's only one very simple special case to learn about.
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/4QSZ5LCWKBDHFR3VRMPVAV2C5JIODSEP/
Code of Conduct: http://python.org/psf/codeofconduct/
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/D52IFGBE54NUHZVFSCKMHRR3JZVLJQUX/
Code of Conduct: http://python.org/psf/codeofconduct/