2

I came across a snippet explaining Continuations using call/cc. In the snippet provided below, what is the continuation for the fn called by call/cc is the entire let block, or the lines below the call/cc ? Also can someone provide an explanation on why the entire let block is not provided as the continuation ?

#lang racket
(define resume-test-3 #f)

(define test-3 (lambda ()
   ; the let defines a variable i local to the lambda, and 
   ; sets its value to 0
   (let ((i 0))
     ;
     (call/cc (lambda (k) (set! resume-test-3 k)))
     ;
     ; The next time the-continuation is called, we start here.
     (displayln "I am back ")
     (set! i (+ i 1))
     ; and return the value i
     i
     )
    ))

(test-3)
(resume-test-3)
(resume-test-3)
Will Ness
  • 70,110
  • 9
  • 98
  • 181
draklor40
  • 453
  • 7
  • 17

2 Answers2

2

The continuation of the call/cc expression consists of the expressions after the call/cc expression. If we add (displayln "Entering let") we can see that invoking the continuation doesn't cause "Entering let" to be printed.

#lang racket
(define resume-test-3 #f)

(define test-3 (lambda ()
   ; the let defines a variable i local to the lambda, and 
   ; sets its value to 0
   (let ((i 0))
     (displayln "Entering let")
     ;
     (call/cc (lambda (k) (set! resume-test-3 k)))
     ;
     ; The next time the-continuation is called, we start here.
     (displayln "I am back ")
     (set! i (+ i 1))
     ; and return the value i
     (displayln "Leaving let")
     i)))

(test-3)
(resume-test-3)
(resume-test-3)

Output:

Entering let
I am back 
Leaving let
1
I am back 
Leaving let
2
I am back 
Leaving let
3
soegaard
  • 30,661
  • 4
  • 57
  • 106
  • I inferred that from the example. In `(+ 1 (call/cc (lambda (k) (k 2))) 3)`, the continuation is `(fn [v] (+ 1 v 2))`. But in the case of `(let (bindings)` the continuation is the state of statements after the call/cc. I guess (and I think I'm right) a let (bindings) can be rewritten as a lambda () with the code inside it in a do block, so the continuation is effectively the set of statements after call/cc – draklor40 Sep 15 '16 at 06:07
2

The implementations rewrites the whole thing into Continuation Passing Style (=CPS):

(define resume-test-3-cps #f)
(define test-3-cps
  (lambda (k)
    ((lambda (kl i) ; this is the "let"
       ((lambda (tk1) (tk1 (set! resume-test-3-cps tk1)))
        (lambda (not-used)
          ((lambda (tk2) (tk2 (displayln "I am back ")))
           (lambda (not-used)
             ((lambda (tk3) (tk3 (set! i (+ i 1))))
              (lambda (not-used)
                ((lambda (tk4) (tk4 (displayln "Leaving let")))
                 (lambda (not-used)
                   ((lambda (tk5) (tk5 i))
                    kl))))))))))
     k 0))) ; variables to "let"

;; top level have barriers, don't know how to simulate them
;; doing full CPS here will make an infinite loop
(test-3-cps values)
(resume-test-3-cps values)
(resume-test-3-cps values)

Notice this works even without using call/cc. Thats because call/cc is just a way to get he features of CPS without having to write it in CPS. There is not much magic when you know how it really works.

Sylwester
  • 47,942
  • 4
  • 47
  • 79