(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.
Well, Kernel has continuations as first class objects (and they aren't functions).
ReplyDeleteContinuation 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
Yes, Kernel's extend-continuation seems even more powerful than this API.
ReplyDeleteTotally 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.
ReplyDelete