[Python-Dev] anonymous blocks
Glyph Lefkowitz
glyph at divmod.com
Tue Apr 19 22:27:57 CEST 2005
Guido van Rossum wrote:
> But what exactly are you trying to accomplish here? I think that
> putting the defs *before* the call (and giving the anonymous blocks
> temporary local names) actually makes the code clearer:
I'm afraid that 'block1', 'block2', and 'doFoo' aren't really making
anything clear for me - can you show a slightly more concrete example?
> def block1(a, b):
> return a + b
> def block2(c, d):
> return c + d
> items.doFoo(block1, block2)
Despite being guilty of propagating this style for years myself, I have
to disagree. Consider the following network-conversation using Twisted
style (which, I might add, would be generalizable to other Twisted-like
systems if they existed ;-)):
def strawman(self):
def sayGoodbye(mingleResult):
def goAway(goodbyeResult):
self.loseConnection()
self.send("goodbye").addCallback(goAway)
def mingle(helloResult):
self.send("nice weather we're having").addCallback(sayGoodbye)
self.send("hello").addCallback(mingle)
On the wire, this would look like:
> hello
< (response) hello
> nice weather we're having
< (response) nice weather we're having
> goodbye
< (response) goodbye
FIN
Note that the temporal order of events here is _exactly backwards_ to
the order of calls in the code, because we have to name everything
before it can happen. Now, with anonymous blocks (using my own pet
favorite syntax, of course):
def tinman(self):
self.send("hello").addCallback(def (x):
self.send("nice weather we're having").addCallback(def (y):
self.send("goodbye").addCallback(def (z):
self.loseConnection())))
Now, of course, this is written as network I/O because that is my
bailiwick, but you could imagine an identical example with a nested
chain of dialog boxes in a GUI, or a state machine controlling a robot.
For completeness, the same example _can_ be written in the same order as
events actually occur, but it takes twice times the number of lines and
ends up creating a silly number of extra names:
def lion(self):
d1 = self.send("hello")
def d1r(x):
d2 = self.send("nice weather we're having")
def d2r(y):
d3 = self.send("goodbye")
def d3r(z):
self.loseConnection()
d3.addCallback(d3r)
d2.addCallback(d2r)
d1.addCallback(d1r)
but this only works if you have a callback-holding object like Twisted's
Deferred. If you have to pass a callback function as an argument, as
many APIs require, you really have to define the functions before
they're called.
My point here is not that my proposed syntax is particularly great, but
that anonymous blocks are a real win in terms of both clarity and
linecount. I'm glad guido is giving them a moment in the limelight :).
Should there be a PEP about this?
More information about the Python-Dev
mailing list