I'm reading the r6rs Scheme report and am confused by the explanation of continuations (I find it to be too dense and lacking of examples for a beginner).

What is this code doing and how does it evaluate to 4? Why does call/cc want an argument that's a function of one argument? How is call/cc's argument used?

(+ 1 (call-with-current-continuation
       (lambda (escape)
         (+ 2 (escape 3)))))
          =⇒ 4

This example is from section 1.11 - Continuations.

  • This should be a perfect question for codereview.stackexchange.com Jul 3, 2012 at 13:53
  • 1
    No it isn't: according to their FAQ, this question fails a ton of the eligibility criteria ...
    – user39685
    Jul 3, 2012 at 13:58
  • 2
    Definitely not a Code Review question - example code; he's going for understanding, not betterment, wasn't written himself.
    – Michael K
    Jul 3, 2012 at 18:44

3 Answers 3


call/cc takes a function with one argument, because that argument will be populated with the "current continuation". The continuation in this case will return to the point "just after" the call/cc, namely where its return value is being set.

Thus, when you call (escape 3), the rest of the expression (the (+ 2 ...)) is abandoned, and 3 is set as the return value of the call/cc. Thus, the (+ 1 (call/cc ...)) is now evaluated as (+ 1 3), hence the result is 4.


Chris' answer is great, but now that I've figured it out I'd like to add a bit more explanation from the perspective of a beginner to continuations.

call/cc examples

I've done (define call/cc call-with-current-continuation) and will use hop (in the manner of "The Seasoned Schemer") to represent the continuation.

ignoring the parameter: normal evaluation

  (lambda (hop)
    (+ 2 3)))
=> 5

hopping the entire expression: also normal evaluation

  (lambda (hop)
    (hop (+ 2 3))))
=> 5

hopping the operator:

  (lambda (hop)
    ((hop +) 2 3))))
=> #<procedure:+>

hopping an operand:

  (lambda (hop)
    (+ 2 (hop 3))))
=> 3

hopping the hopper:

  (lambda (hop)
    (hop hop)))
=> #<continuation>

Basically, using call/cc gives us a way to 'hop' out of an expression, immediately aborting the computation with the specified return value.

There are many more sophisticated ways to use call/cc that I don't understand, but they're not relevant to the OP.


This introduction with a lots of examples helped me understand continuations.

Anyway. These are some examples on how to (ab)use continuations:

(define (pair-up x)
    (call/cc (lambda (continuation)
        ;; recursive helper functions
        (define (pair-up-aux x)
        (if (null? x) 
            (if (null? (cdr x))
                (continuation #f) ; cancel everything and return #f
                (cons (cons (car x) (cadr x)) (pair-up-aux (cddr x)))))) ; build result
        (pair-up-aux x))))

This code takes a list and makes a list of pairs such that (pair-up '(a b c d)) becomes ((a . b) (c . d)). It does so by recursing and chaining conses. When I'm at the end of the list and see that i lack one element to create the last pair I would want to cancel everything and return #f instead. If I did (pair-up '(a b c)) and just returned #f I would have got ((a . b) . #f). The call/cc at the moment gives me chance to change my mind and return something else alltogether even though I have started constructing my return. (continuation #f) returns #f as the result of this procedure since the call/cc is around the functions body. The next example implements a loop with continuations.

(let ((x 0))
    (let ((cont (call/cc (lambda (x) (x x)))))
        (set! x (+ x 1))
        (display x)
        (if (= x 10)
            (display "Finished!\n")
            (cont cont))))

Now this one actually prints 1..10 and calling the continuation will make it do the body of the let several times. I had to use two separate let (or let*) or else x would have been initialized at each run to and x would never ever become 10.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.