[Python-ideas] Is this PEP-able? for X in ListY while conditionZ:
Nick Coghlan
ncoghlan at gmail.com
Sat Jun 29 12:09:54 CEST 2013
On 28 June 2013 18:20, Wolfgang Maier
<wolfgang.maier at biologie.uni-freiburg.de> wrote:
> Let me suggest one more solution although it requires a new keyword:
> introduce
>
> *breakif* condition
>
> and define its translation as if condition: break .
> You can now write
> (x for x in iterable breakif x < 0)
> and I don't see a way how that could possibly be misread by anyone.
> Also it would translate unambiguously to the explicit:
>
> for x in iterable:
> breakif x<0 # itself translating to if x<0: break
> yield x
>
> It would work with genexps, comprehensions and explicit loops alike (with
> very
> little benefit for the later, though maybe it increases readability even
> there
> by making it clear from the start of the line what the purpose of the
> condition
> test is).
This (or, more accurately, a slight variant that doesn't need a new
keyword) actually sounds quite attractive to me. My rationale for that
ties into the just rejected PEP 315, which tried to find an improved
"loop and a half" syntax for Python, as well as the ongoing confusion
regarding the meaning of the "else" clause on while and for loops.
Currently, Python's fully general loop syntax looks like this:
while True:
# Iteration setup
if termination_condition:
break
# Remained of iteration
And the recommended idiom for a search loop looks like this:
for x in data:
if desired_value(x):
break
else:
raise ValueError("Value not found in {:100!r}".format(data))
Rather than adding a new keyword, we could simply expand the syntax
for the existing break statement to be this:
break [if <EXPR>]
This would simplify the above two standard idioms to the following:
while True:
# Iteration setup
break if termination_condition
# Remainder of iteration
for x in data:
break if desired_value(x)
else:
raise ValueError("Value not found in {:100!r}".format(data))
A "bare" break would then be equivalent to "break if True". The "else"
clause on the loop could then be *explicitly* documented as associated
with the "break if <X>" form - the else only executes if the break
clause is never true. (That also becomes the justification for only
allowing this for break, and not for continue or return: those have no
corresponding "else" clause)
Once the break statement has been redefined this way, it *then*
becomes reasonable to allow the following in comprehensions:
data = [x for x in iterable break if x is None]
As with other proposals, I would suggest limiting this truncating form
to disallow combination with the filtering and nested loop forms (at
least initially). The dual use of "if" would make the filtering
combination quite hard to read, and the nested loop form would be
quite ambiguous as to which loop was being broken. If we start with
the syntax restricted, we can relax those restrictions later if we
find them too limiting, while if we start off being permissive,
backwards compatibility would prevent us from adding restrictions
later.
I'd be very keen to see this written up as a PEP - it's the first
proposal that I feel actually *simplifies* the language in any way
(mostly by doing something about those perplexing-to-many else clauses
on for and while loops).
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
More information about the Python-ideas
mailing list