I am disliking this proposal at all, more from a gut-feel than anything.

But then I just did `import this` and pasted bellow the
parts I think this violates. 

While we all have to keep in mind that the "zen of Python" are
more guidelines than absolute standards, they still are
_good_ guidelines that have brought the language 
to where it is. 

So, these are the zen violations that stroke me on first sight:

Simple is better than complex.

Flat is better than nested.
Sparse is better than dense.
Readability counts.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.

--------
Other than that, I am having trouble   to understand
how proper indentation of blocks would work under this proposal. 

Does opening a `[{(` and having any `:` statements inside
just imply one more indentation level? Or can the statements inside
be validly less indented than the line containing the `= [...` opening bracket?

And, just for general, objective feedback, "I am -1 on this". 


On Fri, 21 Feb 2020 at 11:32, Dominik Vilsmeier <Dominik.Vilsmeier@gmx.de> wrote:
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/