Scheme 执行以下call/cc表达式
我使用racket,得到了以下简单代码的结果Scheme 执行以下call/cc表达式,scheme,racket,evaluation,continuations,callcc,Scheme,Racket,Evaluation,Continuations,Callcc,我使用racket,得到了以下简单代码的结果4: (let/cc done ((let/cc esc (done (+ 1 (let/cc k (esc k))))) 3)) 我打算一步一步地执行这个代码 首先,我将第一个let/cc更改为call/cc的形式,如下所示: (call/cc (λ (done) ((let/cc esc (done (+ 1 (let/cc k
4
:
(let/cc done
((let/cc esc
(done (+ 1 (let/cc k
(esc k)))))
3))
我打算一步一步地执行这个代码
首先,我将第一个let/cc
更改为call/cc
的形式,如下所示:
(call/cc (λ (done)
((let/cc esc
(done (+ 1 (let/cc k
(esc k)))))
3)))
当然,这也会产生4
第二,由于我在中找到了call/cc
的机制,其中说call/cc
请执行以下4个步骤:
C
,该函数接受一个参数,并使用该参数值应用当前延续expr
——即调用(expr C)
(expr C)
的结果,除非expr
调用C
,在这种情况下,将返回传递给C
的值call/cc
,我遵循了上述步骤,如下所示:
C
指(λ(x)x)
expr
是(λ(完成)((let/cc-esc(完成(+1(let/cc-k(esc-kщ))3))
,(expr-C)
是:
((λ (done)
((let/cc esc
(done (+ 1 (let/cc k
(esc k)))))
3))
(λ (x) x))
请告诉我我做错了什么。我混淆了延续的概念。谢谢。当口译员看到一个
呼叫/cc
时,即使不执行CPS的口译员也会使用该子树执行该操作。您的代码如下所示:
((λ (done)
((λ (esc)
((λ (k) (esc k))
(λ (r) (k+ done 1 r))))
(λ (v) (v 3))))
values)
; k+ implementation (+, but CPS)
(define (k+ k . args)
(k (apply + args)))
延续不仅仅是闭包(函数)。它们还执行跳转到它们在代码中的定义位置。您必须完全执行CPS转换,才能尝试在Scheme解释器中计算结果表达式。该表达式将只包含
lambda
s,而不包含continuations(在call/cc
(1)的意义上)
您尝试使用的表达式将两者混合在一起-它将done
定义为简单的lambda
定义的函数,但在嵌套上下文中仍将其用作延续
(1) (另一个引起混淆的原因是在continuation传递样式中调用函数参数“continuations”。它们不是真正的continuations;它们是简单的函数,在这种或那种情况下“被调用”,所以通俗地说,它们也被称为“continuations”,尽管它们是“偶然事件”甚至“处理程序”可能会更好。) 另见 按照这种方法,将Scheme代码转换为Common Lisp,我们得到:
;; (let/cc done
;; ((let/cc esc
;; (done (+ 1 (let/cc k
;; (esc k)))))
;; 3))
(prog (retval done arg1 func esc arg2 k arg3 arg4)
(setq done (lambda (x) (setq retval x) (go DONE))) ; 3
(setq arg1 3) ; 5
(setq esc (lambda (x) (setq func x) (go ESC))) ; 8
(setq arg3 1) ; 10
(setq k (lambda (x) (setq arg4 x) (go K))) ; 12
(setq arg4 (funcall esc k)) ; 13
K ; 11 continuation K
(setq arg2 (+ arg3 arg4)) ; 9
(setq func (funcall done arg2)) ; 7
ESC ; 6 continuation ESC
(setq retval (funcall func arg1)) ; 4
DONE ; 2 continuation DONE
(return retval)) ; 1
事实上(在翻译过程中,代码行是按编写顺序编号的)
;; (let/cc done
;; ((let/cc esc
;; (done (+ 1 (let/cc k
;; (esc k)))))
;; 3))
(prog (retval done arg1 func esc arg2 k arg3 arg4)
(setq done (lambda (x) (setq retval x) (go DONE))) ; 3
(setq arg1 3) ; 5
(setq esc (lambda (x) (setq func x) (go ESC))) ; 8
(setq arg3 1) ; 10
(setq k (lambda (x) (setq arg4 x) (go K))) ; 12
(setq arg4 (funcall esc k)) ; 13
K ; 11 continuation K
(setq arg2 (+ arg3 arg4)) ; 9
(setq func (funcall done arg2)) ; 7
ESC ; 6 continuation ESC
(setq retval (funcall func arg1)) ; 4
DONE ; 2 continuation DONE
(return retval)) ; 1