The continuation in this case is the "thing" that receives the return value of the call/cc
invocation. Thus:
(display (call/cc (lambda (k) (k 12)))
has the same result as
(display 12)
Continuations in Scheme "look and feel" like procedures, but they do not actually behave like procedures. One thing that can help you understand continuations better is CPS transformations.
In CPS transformation, instead of a function returning a value, instead it takes a continuation parameter, and invokes the continuation with the result. So, a CPS-transformed sqrt
function would be invoked with (sqrt 64 k)
and rather than returning 8, it just invokes (k 8)
in tail position.
Because continuations (in a CPS-transformed function) are tail-called, the function doesn't have to worry about the continuation returning, and in fact, in most cases, they are not expected to return.
With this in mind, here's a simple example of a function:
(define (hypot x y)
(sqrt (+ (* x x) (* y y))))
and its CPS-transformed version:
(define (hypot x y k)
(* x x (lambda (x2)
(* y y (lambda (y2)
(+ x2 y2 (lambda (sum)
(sqrt sum k))))))))
(assuming that *
, +
, and sqrt
have all been CPS-transformed also, to accept a continuation argument).
So now, the interesting part: a CPS-transformed call/cc
has the following definition:
(define (call/cc fn k)
(fn k k))
With CPS transformation, call/cc
is easy to understand and easy to implement. Without CPS transformation, call/cc
is likely to require a highly magical implementation (e.g., via stack copying, etc.).