[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
I'll take a shot at it. Continuations are a source of great expressive
power and confusion.
As you point out, logically a continuation is a control context
representing "the rest of the program".
The "square egg" explanation is that you capture/copy the stack at the
point of call so that you can go back and re-execute it later, perhaps
Continuations are related to CPS (Continuation Passing Style). Which are
continuations built by hand (er, closure ;^).
(define (factorial n) (if (< n 2) 1 (* n (factorial (- n 1)))
One can think of the stack at the maximum depth of (factorial 5) as:
(factorial 5) => (* 5 (* 4 (* 3 (* 2 (factorial 1)))))
in CPS form of factorial is:
(define (fact n k) ;; k is the continuation, a one argument block closure.
(if (< n 2)
(fact (- n 1) (lambda (result) (k (* result n))
So each "stack frame" is a procedure which does "the rest of the
computation", i.e. do the multiply and return a value to "the rest of the
If you capture this continuation, you can do something else, apply it later
zero or more times.
So if we capture a contination and return it instead of a value this
procedure represents the "rest of the computation", the last bit of which
(* 5 (* 4 (* 3 (* 2 ))))
Where  represents the "hole" where the continuation was captured.
OK, hold on to your seat. Here is where it gets tricky.
> (define (call/cc-fact n)
;; define an "exit procedure" to return the inner continuation
(if (< n 2)
;; return inner continuation
(lambda (k) (exit (lambda (n) (k n)))))
(* n (cc/fact (- n 1))))))
> (call/cc-fact 5)
> (define k (call/cc-fact 5)) ;; captures (* 5 (* 4 (* 3 (* 2 ))))
> (define k2 k)
> (k 1)
> (k2 5)
So what happened was this. Call/cc-fact captured the outer (exit)
continuation **at the point where k was about to be defined**. When we
invoked the continuation (k 1) then the result was computed at the point
where (define k ) was being executed.
So after invoking (k 1) we had the effect of (define k 120).
After (k2 5) we re-defined k as (* 5 4 3 2 5) => 600.
So (call-with-current-continuation <proc>) packages up the "control
context" and hands that as a procedure/closure of one argument to the
Continuations are very useful in implementing debugging, handling
interrupts, REPL command levels, and multithreading. [Hey, I got an
interrupt, let me capture the continuation, service the interrupt and get
back to you. Actually, I have a higher priority thread, so let me invoke
that thread's continuation instead and remember this one's continuation for
Continuations really are too powerful. There are a great many papers
written on how to constrain this power.
Hope the above helps,
> [Original Message]
> From: KELLEHER,KEVIN (Non-HP-Roseville,ex1) <email@example.com>
> To: <firstname.lastname@example.org>
> Date: 2/1/2002 11:37:56 AM
> Subject: continuations
> Continuations may be as simple as can be,
> but I cannot grasp the concept or their use.
> I've been reading Kent Dibvig's "The Scheme Programming
> Language" (among other things) but I just don't get it.
> Could someone suggest a paper I could read (perhaps from
> I'm reminded of how obtuse the use of pointers seemed to
> me when I was learning C. Many explanations limited
> themselves to the statement that a pointer is an address,
> as if that said it all. It does explain everything, but only
> if you already understand it. If you don't, the statement
> is gibberish. You can't jump from that terse statement
> to making a linked list.
> Kevin Kelleher