There's been a discussion of the "for ... else ..." construction in Python. Here's a suggestion as to how we might improve matters, and perhaps usefully extend the language. I hope it might benefit some, without harming anyone else.
Aside: I've not read the whole of the previous discussion, and it may be that some or all of what I say has already been expressed there. So apologies for any missing credits to others. The errors, I'm responsible for.
Here's what happens at present.
for i in items:
LOOP_BODY
else:
print('exit via StopIteration')
I find the following clearer (where 'if break' is a new language 'compound keyword').
for i in items:
LOOP_BODY
if break:
pass
else:
print('exit via StopIteration')
This would now allow us to write
for i in items:
LOOP_BODY
if break:
print('exit via break')
else:
print('exit via StopIteration')
Sometimes a loop has multiple break commands, which have different purposes. So a further extension might be for i in items:
LOOP_BODY
if break left:
print('exit via break left')
elif break right:
print('exit via break right')
elif break:
print('exit via some other break')
else:
print('exit via StopIteration')
To allow this to work, we extend the language to allow commands such as
break left
break right
as well as the usual
break
Here the identifiers 'left' and 'right' look like variable names, but in fact they are labels. The compiler can, and I think should, produce a hard-coded jump from command
break right
to the code block under
elif break right:
This is the basic idea, keeping the syntax close to Python as it now is (but of course adding to the semantics). Some programmers, and I think I'm one, might want a clearer distinction between
for i in items:
LOOP_BODY
if break:
do_something
and
for i in items:
LOOP_BODY
if broke:
do_something
For this reason I tentatively suggest instead
for i in items:
LOOP_BODY
case:
break left:
print('exit via break left')
break right:
print('exit via break right')
break:
print('exit via some other break')
else:
print('exit via StopIteration')
Some people have asked a built-in means to detect, at the end of the iteration, whether theitems was empty to begin with. The syntax could easily provide this, for example via
case:
zero:
print('no items to process')
However, if we adopt this perhaps we'd also like to retain the simpler for ... if break ... else ... construct.
I hope this helps.
--
Jonathan