←back to thread

317 points est | 1 comments | | HN request time: 0.205s | source
Show context
BerislavLopac ◴[] No.17448998[source]
I would like to see adding a comprehension-like filtering clause to for-statements:

    for n in range(100) if n%2:
        print(f'{n} is odd number')
Does anyone know if there is a PEP covering that?
replies(5): >>17449022 #>>17449029 #>>17449035 #>>17449036 #>>17452328 #
eesmith ◴[] No.17449035[source]
Historically there has been much resistance to proposals like this which only save a line. The existing code is, after all:

    for n in range(100):
        if n%2:
            print(f'{n} is odd number')
You proposal also leads to a more ambiguous grammar because the following is currently allowed:

    for n in range(100) if n%2 else range(n):
The ambiguity can be extended with multiple if's, compare:

    for x in range(10) if n%2 if n else range(n):
    for x in range(10) if n%2 if n else range(n) else n**2:
A work-around would be to raise something akin to the "SyntaxError: Generator expression must be parenthesized if not sole argument" that occurs with expressions like "f(b, a for a in range(3))", but that's a lot of work just to save a newline, two indents, and ":", isn't it?
replies(1): >>17449124 #
BerislavLopac ◴[] No.17449124[source]
How is that ambiguity currently handled in comprehensions?

My point is that it would be nice to have a consistent syntax for all for-loops, either being a part of a comprehension or standing on their own.

EDIT:

> You proposal also leads to a more ambiguous grammar because the following is currently allowed:

    for n in range(100) if n%2 else range(n):
Not really, I gives me "NameError: name 'n' is not defined". Unless it is an 'n' defined in the outer scope, of course.
replies(1): >>17449276 #
eesmith ◴[] No.17449276[source]
"How is that ambiguity currently handled in comprehensions?"

A bit poorly. Compare:

  >>> f(1, 2 for x in )
    File "<stdin>", line 1
      f(1, 2 for x in )
                      ^
  SyntaxError: invalid syntax
  >>> f(1, 2 for x in r)
    File "<stdin>", line 1
  SyntaxError: Generator expression must be parenthesized if not sole argument
See how the first one gives the location of the error while the second does not? As I recall, this is because the first can be generated during parsing, while the second is done after the AST is generated, when the position information is no longer present.

That's why the following:

  >>> f(2 for x in X) + g(1, 2 for y in Y) + h(z**2 for z in Z)
    File "<stdin>", line 1
  SyntaxError: Generator expression must be parenthesized if not sole argument
doesn't tell you which generation expression has the problem.

Yes, I meant that if 'n' is defined in an outer scope. The expression I gave is not a syntax error but a run-time error.

replies(1): >>17456971 #
1. BerislavLopac ◴[] No.17456971[source]
This does not answer my question, so I checked -- comprehensions simply do not accept the `else` clause:

    >>> [a for a in range(10) if True else range(2)]
      File "<stdin>", line 1
        [a for a in range(10) if True else range(2)]
                                         ^
    SyntaxError: invalid syntax
And this is the argument why I can't have my wish, because the standard `for` loops have always accepted `if else`, so it would be a backward incompatible change.

That said, I have another idea: an update to the comprehension syntax which would omitting duplication of variables, using a new "for in" construct. For example, this line:

    (x for x in range(100) if x%2)
...could be written as:

    (x for in range(100) if x%2)
Just an idea... :D