The essence of call-with-concurrent-continuation , or call/cc for short, is the ability to capture control points or continuations during program execution. You can then return to these control points by applying them as functions.
Here is a simple example where continuation is not used:
> (call/cc (lambda (k) (+ 2 3))) 5
If you're not using a sequel, it's hard to tell the difference. Here are a few where we actually use it:
> (call/cc (lambda (k) (+ 2 (k 3)))) 3 > (+ 4 (call/cc (lambda (k) (+ 2 3)))) 9 > (+ 4 (call/cc (lambda (k) (+ 2 (k 3))))) 7
When a continuation is called, the control flow returns to where the continuation was captured by call/cc . Recall the call/cc expression as a hole that fills with what is passed in k .
list-iter is a significantly more complex use of call/cc and can be a difficult place to use it. First, here is a usage example:
> (define i (list-iter '(abc))) > (i) a > (i) b > (i) c > (i) list-ended > (i) list-ended
Here is an outline of what is happening:
list-iter returns a procedure with no i arguments.- When
i is called, we immediately take the continuation and pass it to the control-state . When this continuation associated with return is called, we will immediately return to the one who called i . - For each element in the list, we take a new continuation and rewrite the definition of
control-state this new continuation, which means that we will resume the next step 2 from there. - After setting up the
control-state the next time, we pass the current list item back to return continue, resulting in a list item. - When
i is called again, repeat from step 2 until for-each does its job for the entire list. - Call
return with 'list-ended . Since control-state not updated, it will return 'list-ended each time i is called.
As I said, this is a rather complicated use of call/cc , but I hope this is enough to go through this example. For a softer introduction, I would recommend choosing The Seasoned Schemer .
source share