简体   繁体   中英

What is the continuation of call/cc in a let block

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)

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM