作为一个帮助我理解Racket延续性的项目,我决定尝试编写一个不使用可变变量或全局变量的协同例程实现。到目前为止,这是我所拥有的,但是似乎最终陷入了某种僵局。我缺少明显的东西吗?
#!/usr/bin/env racket
#lang racket
(define (make-proc-args args)
(let/cc cc
(cons cc args)))
(define (fork proc)
(let ([current (make-proc-args '())])
(proc current)))
(define (yield to args)
(let ([current (make-proc-args args)])
((car to) current)))
(define c
(fork
(lambda (p)
(let loop ([i 0]
[parent p])
(unless (> i 10)
(loop (+ i 1) (yield parent (list i))))))))
(let loop ([child c])
(println (car child))
(loop (yield child '())))
答案 0 :(得分:1)
(define (make-proc-args args)
(let/cc cc
(cons cc args)))
当被调用时,它作为对象返回其延续。如果您看这段代码:
(define (fork proc)
(let ([current (make-proc-args '())])
(proc current)))
(make-proc-args '())
的延续是绑定了let
和被调用current
的{{1}}的应用。在以下情况下:
proc
这意味着(fork
(lambda (p)
(let loop ([i 0]
[parent p])
(unless (> i 10)
(loop (+ i 1) (yield parent (list i)))))))
将返回时间并调用,并且(yield parent (list i))
将再次被调用。.以(proc current)
和i
开头的租赁。 0
的继续存储,对吗?错了!
yield
捕获的连续性是(define (yield to args)
(let ([current (make-proc-args args)])
((car to) current)))
,碰巧一次又一次地相同。
解决此问题的最简单方法是使延续不调用存储的延续,因为它是自己的延续。因此,您需要执行以下操作:
((car to) current)
请注意,在这两种情况下,延续都是(define (fork proc)
(let/cc cc
(let ([current (cons cc '())])
(proc current))))
(define (yield to args)
(let/cc cc
(let ([current (cons cc args)])
((car to) current))))
和yield
自然返回时发生的情况,而不是fork
的正文完成时发生的情况。
也知道延续是在顶层定界的,所以您也许应该在let
块中测试所有代码,以捕获由于延续在顶层表现不同而可能带来的错误。不允许使用let
作为顶层,但是如果将其放在define
中,则会得到let
作为#<void>
的最后一个值,因为那是值{{1} }形式,而不是您期望的成对。
child
此打印:
define
最后一条提示。也许您应该为延续对象或至少抽象的结构?