Scheme 程序开始时的当前延续

Scheme 程序开始时的当前延续,scheme,racket,continuations,Scheme,Racket,Continuations,创建返回过程显然是使用continuations可以创建的一个常见示例,如下例所示: (define (find-multiple factor) (let/cc return (for ([num (shuffle (range 2000))]) (when (zero? (modulo num factor)) (return num))))) (find-multiple 43) (来自) 虽然我有点理解,开始时的延续是返回到从某个值调用过程的位

创建返回过程显然是使用continuations可以创建的一个常见示例,如下例所示:

(define (find-multiple factor)
  (let/cc return
    (for ([num (shuffle (range 2000))])
      (when (zero? (modulo num factor))
        (return num)))))

(find-multiple 43)
(来自)

虽然我有点理解,开始时的延续是返回到从某个值调用过程的位置,但我不知道延续实际上是什么样子。在下面的示例中,我可以想象它是什么样子:

(define c #f)
(+ 1 (+ 2 (+ 3 (+ (let/cc here (set! c here) 4) 5)))) ; 15
(c 20) ; 31
续页为:

(lambda (something)
  (+ 1 (+ 2 (+ 3 (+ something 5))))
因此表达式被包装到lambda中,
let/cc
被替换为lambda的输入参数


但是对于返回过程,我不知道正确的思考方式是什么,也不知道续集实际上是什么样子。

首先
let/cc
只是
call/cc
的语法糖。这些是平等的:

(let/cc here 
  (set! c here) 4)

(call/cc 
 (lambda (here) 
   (set! c here) 4))
所有代码,无论您如何编写,都将以特定的方式运行,每个操作将执行一个步骤,然后调用程序其余部分的继续部分。这:

(define c #f)
(+ 1 (+ 2 (+ 3 (+ (let/cc here (set! c here) 4) 5)))) ; 15
(c 20) ; 31
变成这样:

((lambda (c k)
   (call/cc&
    (lambda (here k)
      (set! c here)
      (k 4))
    (lambda (v)
      (+& v 5 (lambda (a1)
                (+& 3 a1 (lambda (a2)
                           (+& 2 a2 (lambda (a3)
                                      (+& 1 a3 (lambda (a4)
                                                 (c 20 k))))))))))))
 #f values)
(read&
 (lambda (x)
   (call/cc& 
    (lambda (return& k)
      (define (k- v)
        (-& 4 v k))
      (<& x 4 (lambda (p)
                (if p
                    (k- x)
                    (return& 10 k-)))))                          
    (lambda (v)
      (display& v values)))))
现在请注意,这里的顺序是显式的,最深的表达式首先被处理,因为所有其他表达式都依赖于首先计算它的值。还要注意,每次继续都包括对
(c20)
的调用

以下是所用程序的CPS版本:

(define (+& a b k)
  (k (+ a b)))

(define (call/cc& f k)
  (f (lambda (v ign-k) (k v)) k))
最后一个可能是您所见过的
call/cc
最清晰的实现。虽然代码中的一个看起来很神秘,因为代码不是连续传递样式,但在Scheme系统将其转换为CPS
call/cc
后,CPS甚至不会被视为原语

对于
(find multiple 43)
来说,continuation就是显示结果的REPL。如果您在类似
(+1(find multiple 43))
的地方使用了它,那么继续将是
(lambda(v)(+1 v halt))

编辑

一个简单的例子:

(let ((x (read)))
  (display 
   (call/cc 
    (lambda (return)
      (- 4 (if (< x 4) x (return 10))))))))
这里是&-过程。这些可能已经开始变得熟悉,并有望预测:

(define (<& a b k) (k (< a b)))
(define (-& a b k) (k (- a b)))
(define (display& v k) (k (display v)))
(define (read& k) (k (read)))

(定义(我理解最初的等价性,
let/cc
是糖。但是:(到处都是
&
是故意的吗?)
调用/cc&
=?
+&
是什么意思?我也失去了一点关于所有嵌套
lambda
的跟踪。有没有一个更简单的例子?我不知道我的会变成这样:(
=&
是一个输入错误。
call/cc&
+&
都是相同的CPS版本,没有&。它们都有一个额外的参数,完成后要调用的回调是一步。我甚至提供了它们的定义。我试图添加一个更简单的示例,但是
call/cc
要有任何函数都需要一个little代码。我敦促您使用调试器并逐步完成这两个步骤:)我正在努力理解这一切。您是说该方案(或任何标准实现)是否会将所有代码内部转换为CP?还是这只是一种可视化程序步骤的方法?@Zelphir实现
call/cc
的唯一方法是将代码转换为CP,以前CPS是实现的一个确定阶段,但今天一些实现,如Ikarus,只在涉及
call/cc
的情况下才这样做,而不是by默认值。如果您对如何实现Scheme感兴趣,您可能会对和感兴趣。@Zelphir
call/cc
很困难,因为它作为一种工具泄漏了实现的内部内容。当一个程序用于编写代码时,当它不在尾部时返回时,延续就是程序的其余部分,这一想法很难实现。对于一个程序来说mer调用
(+(return 5)3)
没有意义,除非您知道
(return 4)
也传递了一个类似
(return&4(lambda(v)(+&v3程序的其余部分))