replacing `else` with `then` in `for` and `try`

Steve D'Aprano steve+python at pearwood.info
Thu Nov 2 06:04:10 EDT 2017


On Thu, 2 Nov 2017 12:49 pm, Skip Montanaro wrote:

> I don't know. The word "then" doesn't connote different ways of exiting a
> loop to me ("else" doesn't really either, I will grant you that, but it's
> what we have). Here's how I would read things:
> 
>    - *while* some condition holds, execute the loop, possibly breaking out,
>    *then* do some finishing work
>    - *for* each element in some sequence, execute the loop, possibly
>    breaking out, *then* do some finishing work

And that is exactly the behaviour of the for...else and while...else
construct. You're reading it correctly.

When you say "possibly breaking out", I assume you mean breaking out of the
*entire* compound statement, because the alternative would be just silly. The
alternative would be exactly equivalent to just following the loop with some
unindented code:


while condition:
    block
# on break we jump to here
finishing


In that case, it makes no sense to include a do-nothing "else" or "then"
keyword.

To put it another way, if we are trying to infer the semantics of a statement,
and can interpret it in one of two ways:

- it does something

- it does nothing

then (with special case) of `pass`, we should always assume the first case,
thus resolving the ambiguity in favour of "Guido isn't an idiot who added a
pointless keyword" :-)


> In neither case does it seem to me that you execute the finishing work only
> if you break out of the loop, but not if the loop terminates when the while
> condition becomes false or the for loop's sequence is exhausted.

If I'm reading you correctly, I think you are confused about the `else`
clause. It is incorrect to say that the `else` clause runs "only if you break
out of the loop" (as you say). The `else` clause runs *after* the loop
completes, but NOT if you jump out with break/return/raise.

If we don't jump out of the loop, the else block is equivalent to just
following the loop with unindented code:


for x in sequence:
    block
else:
    follows


is equivalent to:


for x in sequence:
    block
follows


Hence, in the absence of any early exit from the loop, the `else` block
behaves more like an *then* rather than an "else". The behaviour of `else`
confused me utterly until I realised that the semantics of the compound
for...else was the loop to execute, then the `else` block.

So why even bother with `else`?

Unlike the second case, the `else` block is part for the compound for/while
statement. And so `break` doesn't just exit the loop, it exits the whole
compound statement, jumping past the `else`:

for x in sequence:
    block
else:
    follows
# break jumps to here
more code

 
The motive for allowing this pattern is described here:

https://shahriar.svbtle.com/pythons-else-clause-in-loops


> You might
> consider that while/then or for/then actually reads too much like English,
> fooling you into interpreting it as English, opening you up to ambiguity.

If you interpret it as English, it works fine. You run the loop, then you run
the "then" clause. If you jump out of the loop (whether by return, raise or
break) you jump out of the *entire* statement, not just the loop part.

There's no ambiguity because we can assume Guido wouldn't introduce a
pointless block keyword that does literally nothing except require an indent.


> You might argue that "else" doesn't either, but it has the strangely nice
> property of actually being a bit clumsier to read, forcing the reader to
> learn and apply the precise rules of the programming language instead of
> infer the more ambiguous rules of English.

If only that were true... 

There's a simple, obvious, but sadly WRONG plain English interpretation of
for...else, namely that the `else` clause runs if the for sequence was empty:


for x in L:
    pass
else:
    # This is wrong!
    print("L is empty")


and similar for while. That lead me astray for the longest time! And I'm not
the only one.


> English and other natural languages aren't precise enough to serve as
> programming languages. 

Hmmm... I think Hypertalk might have something to say about that.

And Inform7 I think would laugh in your face :-)




-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list