[Python-ideas] Control Flow - Never Executed Loop Body

Sven R. Kunze srkunze at mail.de
Wed Mar 23 19:19:53 EDT 2016


On 23.03.2016 23:11, Andrew Barnert wrote:
> I've said that if be happy to see any counterexamples, where you really do need this with iterators.

1) you conveniently snipped the example I've given: somebody wrote 
functionality assuming a sequence (as innocently as most of the 
contributors to python-list and python-ideas); later the input sequence 
will be changed to an input iterator; "if len(collection)" may hide 
errors then

2) the colleague who basically initiated the whole discussion needed to 
implement some sort of "on-the-fly" converter pulling specific items 
from a third-party system A and pushing the converted items to another 
third-party system B. In case none items are there to be transferred and 
converted, a placeholder item still needs be pushed to system B. [yes, 
that is how somebody can make money; customers sometimes have 
interesting requirements]

> The more complicated the language is, the harder it is to keep it all in your head, to spot the control flow while skimming, to trace out the details when necessary, etc.

And that is exactly why I and other like to see such an addition. It's 
not just the idea of a single person. It reduces the amount of lines of 
code and (for the correct implementation of all corner cases) it has 
less indentation and is presumably faster.

> Only accepting changes that are actually worth the cost in increased complexity is a big part of what makes Python more readable than "dumping-ground" languages that have C-for, Python-for, while, do-while, until, repeat-until, and loop, some in both statement and expression variants, and some also writable in postfix form.

I understand that and want to keep it that way as you do. It seems that 
languages like Django and jinja2, which are 10x more concerned about 
feature reduction than Python, have {% empty %} or {% else %}. So, 
Python would not be the first language to support this feature.

>>> The for loop bytecode would have to change to stash an "any values seen" flag somewhere such that if it sees StopIteration and hasn't seen any values, it converts that to an EmptyCollection. Or any of the other equivalents (e.g., the compiler could unroll the first PyIter_Next from loop from the rest of them to handle it specially).
>> Something like that.
>>
>>> But this seems like it would add a lot of overhead and complexity to every loop whether desired or not.
>> If the "for" does not have any empty-equivalent clauses, there is no need to introduce that overhead in the first place.
> Not true. The first implementation I suggested, putting EmptyCollection into every iterable, requires the overhead in every case. The second one, changing the way the existing bytecodes work, means making frame objects (or _something_) more complicated to enable stashing the flags, which affects every for loop. The third, unrolling the first PyObject_Iter, has to be done if there's any code that can inspect the current exception state, which can't be statically determined, so it has to be always done.
>
> If you have a _different_ implementation, I'm happy to hear it. I supplied all the versions I could think of because another critic (Stephen? I forget...) implied that what you wanted was impossible or incoherent, and it clearly isn't. But it may not be a good idea to let a critic of your idea come up with the implementation. :)

Not sure if that can be easily done, but as I understand it, there would 
be two alternative bytecode implementations available. Depending on 
whether the "for" has an "empty"-equivalent clause, the 
"emptified/except/slow for" is used. If the "for" doesn't have such 
clause, the "original" "for" is used.

So, depending on the actual code, the bytecode is different. Does this 
makes sense?

>> So we can conclude:
>>
>> 1) none overhead for regular "for"s
>> 2) less overhead for "for-ifempty" because it would be done in C and not in Python
> [snip]
> No, because, as I just explained, the old protocol is  taken care of by wrapping old-style sequences in iterator objects, so as far as the for-loop code is concerned, they look identical to "new-style" iterables.

Oh, then I had interpreted what you said the wrong way. Thanks for 
explaining again.

> But that's just an extra rule to implement (and remember) for no real benefit. Why not just document that for/except/else is generally useless and shouldn't be written, and let linters flag it?

Good idea!

> Because there's already something in the language that you find confusing, that gives us free rein to add anything else to the language that people will find confusing?

I am open for suggestions. My argument here is that "except 
StopIteration" is not better/worse than "else" but the former is extensible.


Best,
Sven



More information about the Python-ideas mailing list