I suggest starting with the question: what does it mean to be a first-class continuation?
A continuation of an expression essentially consists of two pieces of data: first, the closure (that is, the environment) of that expression; and secondly, an idea of โโwhat should be done with the result of the expression. Thus, a first-class continuation language is one that has data structures that encapsulate these parts, and that processes these data structures just like any other.
call / cc is a particularly elegant way to implement this idea: the current sequel is packaged as a procedure that encapsulates what needs to be done using an expression, like what the procedure does when applied to an expression; to represent a continuation in this way simply means that closing this procedure contains the environment on the site to which it was called.
You could imagine realizing the idea of โโfirst-class continuations in other ways. They will not call / cc, and itโs hard for me to imagine how such a presentation could be simpler.
In the split note, consider the let / cc implementation mentioned by Eli, which I prefer to call bind / cc:
(define-syntax bind/cc (syntax-rules () ((bind/cc var . body) (call/cc (lambda (var) . body)))))
And as an exercise, how would you implement call / cc based on bind / cc?
Charles Stewart
source share