[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