This idea occurred to me in context of PEP 479 and the "or stop()" hack for generator expressions. I'm not a big enough fan of the idea to pursue it myself, but if anyone is bothered by the prospect of PEP 479 taking the "or stop()" technique away, this may be worth pursuing further.

As a reminder of how the hack works, the following generator:

>>> def takewhile(iterable, pred):
...     for x in iter(iterable):
...         if not pred(x):
...             return
...         yield x
>>> list(takewhile(range(10), (lambda x: x < 5)))
[0, 1, 2, 3, 4]

Can currently be converted to a generator expression with the aid of a helper function:

>>> def stop():
...     raise StopIteration
>>> list(x for x in range(10) if x < 5 or stop())
[0, 1, 2, 3, 4]

Under PEP 479, that will raise RuntimeError instead. If return was an expression rather than a statement (ala the yield statement -> expression conversion in PEP 342), then the following would be functionally equivalent to the current "or stop()" trick:

>>> list(x for x in range(10) if x < 5 or return)
[0, 1, 2, 3, 4]

This is emphatically *not* executable pseudocode - it only makes sense in terms of the translation to the corresponding full generator function definition. However, the translation remains exact in terms of the normal semantics of the "return" keyword, unlike various other proposals to use the "while" keyword to provide comparable functionality.

For comprehensions, the meaning of a bare return would likely need to be tweaked slightly to be the same as reaching the end of the frame: returning the object being constructed by the comprehension, rather than None.

>>> [x for x in range(10) if x < 5 or return]
[0, 1, 2, 3, 4]
>>> {x for x in range(10) if x < 5 or return}
{0, 1, 2, 3, 4}
>>> {x:x for x in range(10) if x < 5 or return}
{0:0, 1:1, 2:2, 3:3, 4:4}


Nick Coghlan   |   |   Brisbane, Australia