Prev Up Next
The operator call-with-current-continuation calls its argument, which must be a unary procedure,
with a value called the ``current
continuation''. If nothing else, this explains the
name of the operator. But it is a long name, and is
often abbreviated
call/cc.4
The current continuation at any point in the execution
of a program is an abstraction of the rest of the
program. Thus in the program
(+ 1 (call/cc
(lambda (k)
(+ 2 (k 3)))))
the rest of the program, from the point of view of the
call/cc-application, is the following
program-with-a-hole (with representing the
hole):
(+ 1 )
In other words, this continuation is a program that
will add 1 to whatever is used to fill its hole.
This is what the argument of call/cc is called
with. Remember that the argument of call/cc is
the procedure
(lambda (k)
(+ 2 (k 3)))
This procedure's body applies the continuation (bound
now to the parameter k) to the argument 3.
This is when the unusual aspect of the continuation
springs to the fore. The continuation call abruptly
abandons its own computation and replaces it with the
rest of the program saved in k! In other words,
the part of the procedure involving the addition of
2 is jettisoned, and k's argument 3 is sent
directly to the program-with-the-hole:
(+ 1 )
The program now running is simply
(+ 1 3)
which returns 4. In sum,
(+ 1 (call/cc
(lambda (k)
(+ 2 (k 3)))))
=> 4
The above illustrates what is called an escaping continuation, one used to exit out of a
computation (here: the (+ 2 ) computation). This
is a useful property, but Scheme's continuations can
also be used to return to previously abandoned
contexts, and indeed to invoke them many times. The
``rest of the program'' enshrined in a continuation is
available whenever and how many ever times we choose to
recall it, and this is what contributes to the great
and sometimes confusing versatility of call/cc. As
a quick example, type the following at the listener:
(define r #f)
(+ 1 (call/cc
(lambda (k)
(set! r k)
(+ 2 (k 3)))))
=> 4
The latter expression returns 4 as before. The
difference between this use of call/cc and the
previous example is that here we also store the
continuation k in a global variable r.
Now we have a permanent record of the continuation in
r. If we call it on a number, it will return that
number incremented by 1:
(r 5)
=> 6
Note that r will abandon its own continuation,
which is better illustrated by embedding the call to
r inside some context:
(+ 3 (r 5))
=> 6
The continuations provided by call/cc are thus
abortive continuations.
4 If your Scheme does not already have this
abbreviation, include
(define call/cc call-with-current-continuation) in
your initialization code and protect yourself from
RSI.
Prev Up Next