I've been pondering about how to implement continuations in my Psil interpreter. One choice is to redesign the whole thing to use continuation-passing style with the resulting performance hit. I've been putting off trying to do that.
It occurred to me to have a look at Stackless, which is a variant of Python that supports lightweight threads called "tasklets". It turns out this is ideal. Here is the complete implementation of continuations:
def call_with_current_continuation(f): import stackless channel = stackless.channel() stackless.tasklet(f)(channel.send) return channel.receive()
That's it! Calling stackless.tasklet()
creates a new tasklet object that will be scheduled later by Stackless. The function f
is expected to take one parameter, which is itself a function that takes one parameter that will be returned from call_with_current_continuation
. It turns out that channel.send
is exactly such a function (bound member functions in Python are great). Then calling channel.receive()
stops the current tasklet and waits for the new one to call channel.send
with a parameter. Finally, the value is returned from call_with_current_continuation
.
It took me a while to come up with this concise implementation, after reading the sparse Stackless documentation and tutorial. I had to let the concept of continuations and the philosophy of Stackless sink in a bit before this implementation became clear. I'm quite pleased with it.
2009-02-04T18:49:09Z