2016-09-14 10 views
1

Я наткнулся на фрагмент, объясняющий Continuations, используя call/cc. В приведенном ниже фрагменте, что является продолжением для fn, вызываемого вызовом/cc, является весь блок let или строки ниже вызова/cc? Также может ли кто-нибудь объяснить, почему весь блок let не предоставляется в качестве продолжения?Что является продолжением вызова/cc в блоке let

#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) 

ответ

1

Продолжение выражения call/cc состоит из выражений после выражения call/cc. Если мы добавим (displayln "Entering let"), мы можем увидеть , что вызов продолжения не вызывает «Enter let let» для печати.

#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) 

Выход:

Entering let 
I am back 
Leaving let 
1 
I am back 
Leaving let 
2 
I am back 
Leaving let 
3 
+0

Я предположил, что из примера. В '(+ 1 (вызов/cc (lambda (k) (k 2))) 3)', продолжение - '(fn [v] (+ 1 v 2))'. Но в случае '(let (bindings)' продолжение - это состояние операторов после вызова/cc. Я думаю (и я думаю, что я прав) let (bindings) можно переписать как lambda() с код внутри него в блоке do, поэтому продолжение - это фактически набор операторов после вызова/cc – draklor40

1

Реализация переписывает все это в продолжение 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) 

Обратите внимание, это работает даже без использования call/cc. Это потому, что call/cc - это просто способ получить его функции CPS, не записывая его в CPS. Мало того, что вы знаете, как это работает.