[Python-Dev] anonymous blocks

Shane Holloway (IEEE) shane.holloway at ieee.org
Wed Apr 20 07:10:20 CEST 2005


> *If* we're going to create syntax for anonymous blocks, I think the
> primary use case ought to be cleanup operations to replace try/finally
> blocks for locking and similar things. I'd love to have syntactical
> support so I can write

I heartily agree!  Especially when you have very similar try/finally 
code you use in many places, and wish to refactor it into a common area. 
  If this is done, you are forced into a callback form like follows::


     def withFile(filename, callback):
         aFile = open(filename, 'r')
         try:
            result = callback(aFile)
         finally:
            aFile.close()
         return result

     class Before:
         def readIt(self, filename):
             def doReading(aFile):
                 self.readPartA(aFile)
                 self.readPartB(aFile)
                 self.readPartC(aFile)

             withFile(filename, doReading)

Which is certainly functional.  I actually use the idiom frequently. 
However, my opinion is that it does not read smoothly.  This form 
requires that I say what I'm doing with something before I know the 
context of what that something is.  For me, blocks are not about 
shortening the code, but rather clarifying *intent*.  With this proposed 
change, the code becomes::

     class After:
         def readIt(self, filename):
             withFile(filename):
                 self.readPartA(aFile)
                 self.readPartB(aFile)
                 self.readPartC(aFile)

In my opinion, this is much smoother to read.  This particular example 
brings up the question of how arguments like "aFile" get passed and 
named into the block.  I anticipate the need for a place to put an 
argument declaration list.  ;)  And no, I'm not particularly fond of 
Smalltalk's solution with "| aFile |", but that's just another opinion 
of aesthetics.


Another set of question arose for me when Barry started musing over the 
combination of blocks and decorators.  What are blocks?  Well, obviously 
they are callable.  What do they return?  The local namespace they 
created/modified?  How do blocks work with control flow statements like 
"break", "continue", "yield", and "return"?  I think these questions 
have good answers, we just need to figure out what they are.  Perhaps 
"break" and "continue" raise exceptions similar to StopIteration in this 
case?

As to the control flow questions, I believe those answers depend on how 
the block is used.  Perhaps a few different invocation styles are 
applicable.  For instance, the method block.suite() could return a tuple 
such as (returnedValue, locals()), where block.__call__() would simply 
return like any other callable.

It would be good to figure out what the control flow difference is between::

     def readAndReturn(self, filename):
         withFile(filename):
             a = self.readPartA(aFile)
             b = self.readPartB(aFile)
             c = self.readPartC(aFile)
             return (a, b, c)

and::

     def readAndReturn(self, filename):
         withFile(filename):
             a = self.readPartA(aFile)
             b = self.readPartB(aFile)
             c = self.readPartC(aFile)
         return (a, b, c)

Try it with yield to further vex the puzzle.  ;)

Thanks for your time!
-Shane Holloway


More information about the Python-Dev mailing list