Wednesday, August 1, 2012

An alternative API for continuations

Call/cc is the most well-known API for exposing first-class continuations to userland. But there is another API that's used in Scheme 48 and is also described in a paper by Feeley.

(continuation-capture f) --- calls f with the current continuation as argument. In contrast to call/cc, the continuation is not a procedure, but an opaque first-class object. (In Scheme 48, this is called primitive-cwcc.)

(continuation-graft k thunk) --- calls thunk in the continuation k. In contrast to call/cc, k doesn't receive a value computed in another continuation, but rather thunk's effect is performed in k. (Scheme 48: with-continuation.)

The implementation difference to call/cc is minimal, and expressing call/cc in terms of this API is simple:

(define (call/cc f)
  (continuation-capture
    (lambda (k)
      (f (lambda (val)
           (continuation-graft k (lambda () val)))))))

I can't exactly put my finger on it, but this API seems more powerful than call/cc. In the implementation of delimited dynamic binding in terms of continuation marks I'm working on, there is a need for fetching the marks of another continuation. With call/cc this is impossible, but with this API I can prepend a thunk to the continuation in question, then in this thunk fetch the continuation's marks, and then jump out of it again.

3 comments:

Andres Navarro said...

Well, Kernel has continuations as first class objects (and they aren't functions).

Continuation capture can be done with either call/cc or $let/cc. Then you have apply-continuation to call them (checking guards), guard-continuation to add guards, and extend continuation to add code (in the form of thunks).

Andres Navarro

Manuel Simoni said...

Yes, Kernel's extend-continuation seems even more powerful than this API.

Vladimir Sedach said...

Totally agree. Representing continuations as functions doesn't make sense when they're first-class and not just a compiler technique. It's a lot easier to think of them in terms of stacks, too.