[Python-ideas] for/else statements considered harmful
Ethan Furman
ethan at stoneleaf.us
Thu Jun 7 15:52:49 CEST 2012
Nick Coghlan wrote:
> On Thu, Jun 7, 2012 at 11:06 PM, Alice Bevan–McGregor
> <alice at gothcandy.com> wrote:
>> On 2012-06-07 00:53:22 +0000, Nick Coghlan said:
>>> for x in range(20):
>>> if x > 10:
>>> break
>>> except break:
>>> # Bailed out early
>>> else:
>>> # Reached the end of the loop
>>
>> Seems a not insignifigant number of readers got fixated on the alternate
>> keyword for the current behaviour of else (finally in my example) and
>> ignored or misinterpreted the -really important part- of being able to
>> detect if the loop was skipped (no iterations performed; else in my
>> example).
>>
>> Being able to have a block executed if the loop is never entered is vitally
>> important so you can avoid expensive or potentially impossible length checks
>> on the iterator before the loop. Take this example:
>>
>> sock = lsock.accept()
>> for chunk in iter(partial(sock.recv, 4096), ''):
>> pass # do something with the chunk
>> else:
>> pass # no data recieved before client hangup!
>>
>> Using a temporary varable to simulate this is… unfortunate.
>>
>> sock = lsock.accept()
>> has_data = False
>> for chunk in iter(partial(sock.recv, 4096), ''):
>> has_data = True
>> pass # do something with the chunk
>>
>> if not has_data:
>> pass # no data recieved before client hangup!
>>
>> empty woud be a good keyword to preserve the existing meaning of else, but
>> I'm pretty sure that's a fairly common variable name. :/
>
> Yeah, it's usually fairly important on here to separate out "this is
> the problem I see" from "this is a proposed solution". Getting
> agreement on the former is usually easier than the latter, since there
> are so many additional constraints that come into play when it comes
> to considering solutions. And if we can't even reach agreement that a
> problem needs to be solved, then talking about solution details isn't
> especially productive (although it can be fun to speculate about the
> possibilities anyway).
>
> FWIW, I usually solve this particular problem with for loops by using
> the iteration variable itself to hold a sentinel value:
>
> sock = lsock.accept()
> chunk = None
> for chunk in iter(partial(sock.recv, 4096), ''):
> pass # do something with the chunk
>
> if chunk is None:
> pass # no data recieved before client hangup!
>
> If "None" is a possible value in the iterable, then I'll use a
> dedicated sentinel value instead:
>
> var = sentinel = object()
> for var in iterable:
> ...
> if var is sentinel:
> ...
>
> I've never found either of those constructs ugly enough to
> particularly want dedicated syntax to replace it, and the availability
> of this approach is what makes it especially difficult to push for
> dedicated syntactic support (since all that can really be saved is the
> assignment that sets up the sentinel value).
This seems like a good work-around (meaning: I'll definitely use it,
thanks!), but it does not address the confusion issues.
I think the main problem with the current while/else, for/else is
two-fold: 1) we have two failure states (empty from the start, and
desired result not met), and 2) even though the else is more similar to
the else in try/except/else, it is formatted *just like* the if/else.
Perhaps the solution is to enhance for and while with except?
sock = lsock.accept()
for chunk in iter(partial(sock.recv, 4096), ''):
pass # do something with the chunk
except:
pass # no data recieved before client hangup!
else:
pass # wrap-up processing on chunks
~Ethan~
More information about the Python-ideas
mailing list