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?