[Python-Dev] PEP 340: Deterministic Finalisation (new PEP draft, either a competitor or update to PEP 340)

Nick Coghlan ncoghlan at gmail.com
Sun May 8 22:54:56 CEST 2005


Josiah Carlson wrote:
> The argument over whether blocks should loop, I believe has been had;
> they should.  The various use cases involve multi-part transactions and
> such.

The number of good use cases for a looping block statement currently stands at 
exactly 1 (auto_retry). Every other use case suggested (locking, opening, 
suppressing, etc) involves factoring out try statement boiler plate that is far 
easier to comprehend with a single pass user defined statement. A single pass 
user defined statement allows all such code to be factored safely, even if the 
main clause of the try statement uses break or continue statements.

The insanity of an inherently looping block statement is shown by the massive 
semantic differences between the following two pieces of code under PEP 340:

   block locking(the_lock):
       for item in items:
           if handle(item):
               break

   for item in items:
       block locking(the_lock):
           if handle(item):
               break

With a non-looping user defined statement, you get the semantics you would 
expect for the latter case (i.e. the for loop is still terminated after an item 
is handled, whereas that won't happen under PEP 340)

For the one good use case for a user defined loop (auto_retry), I initially 
suggested in my redraft that there be a way of denoting that a given for loop 
gives the iterator the opportunity to intercept exceptions raised in the body of 
the loop (like the PEP 340 block statement). You convinced me that was a bad 
idea, and I switched to a simple iterator finalisation clause in version 1.2.

Even with that simplified approach though, *using* auto_retry is still very easy:

   for attempt in auto_retry(3, IOError):
       stmt attempt:
           do_something()

It's a little trickier to write auto_retry itself, since you can't easily use a 
generator anymore, but it still isn't that hard, and the separation of concerns 
(between iteration, and the customised control flow in response to exceptions) 
makes it very easy to grasp how it works.

>>>The closest thing to a generic solution I can come
>>>up with would be to allow for the labeling of for/while loops, and the
>>>allowing of "break/continue <label>", which continues to that loop
>>>(breaking all other loops currently nested within), or breaks that loop
>>>(as well as all other loops currently nested within).

Or, we simply have user defined statements which are not themselves loops, and 
use them to create named blocks:

   def block(name):
       try:
           yield
       except TerminateBlock, ex:
           if not ex.args or ex.args[0] != name
               raise

stmt block('foo'):
     while condition():
         stmt block('goo'):
             for ... in ...:
                 while other_case():
                     stmt block('hoo'):
                         if ...:
                             # Continue the inner while loop
                             continue
                         if ...:
                             # Exit the inner while loop
                             raise TerminateBlock, 'hoo'
                         if ...:
                             # Exit the for loop
                             raise TerminateBlock, 'goo'
                         # Exit the outer while loop
                         raise TerminateBlock, 'foo'

This has the benefit that an arbitrary block of code can be named, and a named 
TerminateBlock used to exit it.

> That is a mechanism, but I like it even less than the one I offered. 
> Every time that one wants ot offer themselves the ability to break out
> of a different loop (no continue here), one must create another
> try/except clause, further indenting, and causing nontrivial try/except
> overhead inside nested loops.

Ah well, that criticism applies to my suggestion, too. However, I suspect any 
such implementation is going to need to use exceptions for the guts of the flow 
control, even if that use isn't visible to the programmer.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------
             http://boredomandlaziness.blogspot.com


More information about the Python-Dev mailing list