我使用了球拍,我得到了结果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
。
其次,因为我在internet中找到了call/cc
的机制,其中call/cc
执行了以下4个步骤:
C
,并将当前的continuation应用于该参数值。expr
---即调用(expr C)
。(expr C)
的结果,除非expr
调用C
,在这种情况下,将返回传递给C
的值。因此,我按照第一个call/cc
的上述步骤进行了操作:
C
指的是(λ (x) x)
。expr
为(λ (done) ((let/cc esc (done (+ 1 (let/cc k (esc k))))) 3))
,(expr C)
为:
((λ (done)
((let/cc esc
(done (+ 1 (let/cc k
(esc k)))))
3))
(λ (x) x))
但是,上面的代码(由我修改)不会执行并产生错误:
申请:不是程序;
期望一个可以应用于参数的过程
给出:4...参数:
3
请问我做错了什么。我混淆了延续的概念。感谢。
答案 0 :(得分:1)
当口译员看到call/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)))
答案 1 :(得分:0)
Continuations不仅仅是闭包(函数)。他们还在代码中执行 jump 到他们的定义位置。您必须完整执行CPS转换以尝试在Scheme解释器中评估结果表达式。该表达式仅包含lambda
s且没有延续(在call/cc
(1) 的意义上)。
您尝试的表达式将它们混合在一起 - 它将done
定义为简单的lambda
定义的函数,但它仍然在嵌套的上下文中用作延续。
(1)另一个混乱的来源是在继续传递样式“continuations”中调用函数参数。它们 不 ;它们是在这种或那种可能性中“被称为”的简单功能,因此描述性地它们也被称为“延续”。
另见another example of call/cc code translation。
按照这种方法,将您的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
(setq arg2 (+ arg3 arg4)) ; 9
(setq func (funcall done arg2)) ; 7
ESC ; 6
(setq retval (funcall func arg1)) ; 4
DONE ; 2
(return retval)) ; 1
确实是returns 4(在翻译过程中,代码行按编写顺序编号)。