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
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.