Scheme 程序开始时的当前延续
创建返回过程显然是使用continuations可以创建的一个常见示例,如下例所示: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) (来自) 虽然我有点理解,开始时的延续是返回到从某个值调用过程的位
(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系统将其转换为CPScall/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感兴趣,您可能会对和感兴趣。@Zelphircall/cc
很困难,因为它作为一种工具泄漏了实现的内部内容。当一个程序用于编写代码时,当它不在尾部时返回时,延续就是程序的其余部分,这一想法很难实现。对于一个程序来说mer调用(+(return 5)3)
没有意义,除非您知道(return 4)
也传递了一个类似(return&4(lambda(v)(+&v3程序的其余部分))
。