Scheme 中的协程(R5RS)

问题描述 投票:0回答:2

所以我第一次在lua中遇到协程的概念,lua的实现或多或少是可以理解的。我现在正在学习scheme,我明白相同的功能是通过call/cc实现的,但是我有一点我很难弄清楚如何才能实现这一目标。有人知道简单的教程或有关该主题的内容吗?

lua scheme coroutine callcc
2个回答
1
投票

Matt Might 写了一篇关于延续的很好的介绍,其中包括关于协程的部分:

http://matt.might.net/articles/programming-with-continuations--exceptions-backtracking-search-threads-generators-coroutines/


0
投票

Matt Might 的链接很好,我上次访问rosettacode wiki 中的 Amb 实现时访问过该链接。但对于协程来说,它只是显示

    “协作多线程”(即协程)可以通过Continuations实现(恕我直言,
  1. co例程意味着co通信例程以区别于生成器,也可以“暂停和恢复”
  2. 协作多线程的屈服行为
  3. API
由于线程队列,API 似乎有点对称,而

lua 使用 yield, resume

,由于调用者/被调用者关系,它应该是不对称的。 此 QA“对称协程”链接中很好地展示了对称与非对称。

所以恕我直言,根据OP的背景,Matt Might的链接对OP没有额外的帮助。

c2 wiki
中的

(coroutine routine)
很有帮助,它是非对称的(如上面的 QA 链接所示,非对称版本可以通过一个额外的调度程序实现对称)。

该非对称版本不允许在协程本身中使用协程之间传递数据,但我们可以通过在

cond

 中添加子句并使用 
call/cc
 传递值来进行一些修改来实现这一点。 (请参阅以下
(current passed-arg)
上下文。)

(define (coroutine routine) (let ((current routine) (status 'suspended)) (lambda args (cond ((null? args) (if (eq? status 'dead) (error 'dead-coroutine) (let ((continuation-and-value (call/cc (lambda (return) (let ((returner (lambda (value) (call/cc (lambda (next) (return (cons next value))))))) (current returner) (set! status 'dead)))))) (if (pair? continuation-and-value) (begin (set! current (car continuation-and-value)) (cdr continuation-and-value)) continuation-and-value)))) ((eq? (car args) 'status?) status) ((eq? (car args) 'dead?) (eq? status 'dead)) ((eq? (car args) 'alive?) (not (eq? status 'dead))) ((eq? (car args) 'kill!) (set! status 'dead)) (true nil))))) (define test-coroutine-1 (coroutine (lambda (yield) (print "HELLO!") (yield 1) (print "WORLD!") (yield 2) (print "SORRY, I'M OUT")))) ;; added (define print write-line) (test-coroutine-1 'status?) ; suspended (test-coroutine-1 'dead?) ; #f (test-coroutine-1 'alive?) ; #t (test-coroutine-1) ; "HELLO!" ; 1 (test-coroutine-1) ; "WORLD!" ; 2 (test-coroutine-1) ; "SORRY, I'M OUT" (test-coroutine-1 'status?) ; dead (test-coroutine-1 'dead?) ; #t (test-coroutine-1) ; . error: dead-coroutine
这里用了2个

call/cc

return
就是用
yield
退出协程,做完某件事之后再返回到另一个协程(即这里的交互程序)。 
next
是使用一个
value
后存储之前的悬挂位置。

然后当稍后

再次

调用
(test-coroutine-1)时,我们将从之前使用value
的位置继续运行,例如: 
(yield 1)
 被分配为 
returner
,因为 
(current returner)
,其中 
current
 之前被分配为 
next

yield

 行为意味着我们可以在 
cond
 中添加一个 
(current passed-arg)
 子句,这样 
(yield foo)
 就会按预期被分配到 
passed-arg
,从而实现
通信

因此,

“协程的基本特征”(即保留数据和控制历史记录)是通过 call/cc 实现的。

© www.soinside.com 2019 - 2024. All rights reserved.