A collection of articles, ideas, and rambling from a guy who wrote some software that one time.

Sunday, February 05, 2006

Block Syntax for Python

If you can't have the Python syntax you love, love the Python syntax you have

So, apparently, someone proposed this in #twisted yesterday:

def foo():
@x.doSomethingDeferred().addCallback
def something(result):
return result.stuff()
@something.addErrback
def somethingElse(f):
err = f.trap(FooError)
handle(err)
return retry()
return something


I wasn't there to hear it, and I am told that they were shouted down because it is so obviously a horrible idea.

I don't think that it's a horrible idea. I think it is awesome.

It had never before occurred to me that decorators could be used to implement what is almost (but not quite) block syntax for Python. Since block syntax is my all-time highest priority for Python syntax, the fact that this moves things one step closer makes me happy.

In fact, I'd go so far as to say that I'd like to propose that Deferreds gain a few extra features so that you can spell it in a slightly more expressive way:

def foo():
@x.doSomethingDeferred()
def something(result):
return result.stuff()
@something.Except(FooError)
def somethingElse(err):
handle(err)
return retry()
return something


This idiom effectively turns @-at-function-scope into a symbol meaning "do something asynchronous". Hooray! The only reaction I've heard to this so far is JP and Itamar, both calling for my immediate assassination. I'm sure that will be a popular sentiment among Twisted developers. Anyone else who doesn't think I should be killed for echoing this proposal, though?


Update: The first example I posted is a syntax error - due to a misfeature of decorators that, ironically enough, another Twisted developer objected to when it was introduced. As this is a horrible language abuse to improve readability rather than to some other end, I'm not sure I could seriously argue that the idiom should be @apply(lambda: x.doSomethingDeferred().addCallback). I suppose I'll have to go back to getting some real work done today instead...

4 comments:

fzzzy said...

I think this is great. It solves the biggest problem with the lack of anonymous blocks in Python: The fact that you have to define a named closure before you can refer to it. With this syntax, you can say "I am about to define a named function, but the name doesn't really matter. I am indicating how I am using it before I am defining it."

Brilliant.

jerub said...

Something to note.

addBoth(foo, bar) looks like:

@d.addErrback
def foo(e): print e
@d.addCallback
def bar(x): print x

not the other way around... just a thought

darius said...

Great idea. The syntax reminds me of when-catch in E.

jerub said...

really? what's the difference?