How do I learn Scheme's call-with-current-continuation (call/cc)? I want to know what it is, what it is used for, and how it can be implemented (e.g. added to a metacircular evaluator). Are there any resources for someone who has just finished reading SICP?
It's like setjump
Think of the Scheme program as a tree. Imagine that it is evaluated by replacing each node with its value, starting from the leafs. So if you have (/ (+ 1 2) 3)
, evaluating (+ 1 2)
will give you (/ 3 3)
, etc. Now if you consider any node in the original tree, its continuation will be this replacement. For example, for (+ 1 2)
the continuation will be (lambda (v) (/ v 3))
, for the 3 it will be (lambda (v) (/ (+ 1 2) v))
, and so on.
call/cc
will work in this as a "shortcut". It gives you a continuation, something like a function, that also replaces the whole tree. Consider the following example:
(+ 1
(call/cc
(lambda (k)
(+ 5 (k (+ 1 2))))))
First, we evaluate (+ 1 2)
:
(+ 1
(call/cc
(lambda (k)
(+ 5 (k 3)))))
Now k
, the continuation, is invoked, and instead of just replacing it with a value, we replace the whole tree with the value passed to it!
(+ 1 3)
You can see that it skipped the whole (+ 5 ...)
thing.
Or something like this, I hope this gives you a general idea. I cheated and ignored a few things (evaluating 1==, ==+
, etc., plus first we should evaluate (call/cc λ)
to (λ k)
and so on), but I am already late from work so I hope at least this will be of some help and it doesn't just confuse you further.
>>3
Why would I want to use call/cc
? I don't see why I would ever need something like that.
>>4
You can use it to implement all kinds of fancy control structures: early exit, exceptions, backtracking, engines, co-routines, and so on.
http://wiki.c2.com/?CallWithCurrentContinuation
If you're a C programmer, you might find this explanation easier: in C, you can take a pointer to a function. In C, you also have a return statement. Suppose the return statement were a function (which never returned, of course). It would take a parameter of the same type as the return type of the function it was returning from. Now suppose you could take its address. You could store that address in a variable or pass it as a parameter, and allow functions to return on your behalf. That's what call/cc allows you to do. You can use it as a replacement for throw and catch, or you can set up coroutines with it