Coroutine Problem

例1

```(require (lib "defmacro.ss"))
(define-macro coroutine
(lambda (x . body)
`(letrec ((+local-control-state
(lambda (,x) ,@body))
(resume
(lambda (c v)
(call/cc
(lambda (k)
(set! +local-control-state k)
(c v))))))
(lambda (v)
(+local-control-state v)))))

(letrec ((cor1 (coroutine x
(display "coroutine 1")
(resume cor2 x) ;; ------------------ (1)
(display "resumed 1")))
(cor2 (coroutine x
(newline)
(display "coroutine 2")
(resume cor1 x) ;; ------------------ (3)
(display "resumed 2")))

)
(cor1 "HI1") ;;---------------------------------------------- (2)
(cor2 "HI2")
)

```

分析

(cor1 "HI1") 第一次被调用时，执行的是宏展开以后的函数：

```;; cor1
(lambda (x)
(display "coroutine 1")
(resume cor2 x) ; --------------------------(1)
(display "resumed 1"))
```

```;; cor2
(lambda (x)
(display "coroutine 2")
(resume cor1 x) ;--------------------------- (3)
(display "resumed 2"))
```

…… 似乎一切应该正常，但是为什么出现死循环：

```sumed 2resumed 1resumed 2resumed 1resumed 2resumed 1resumed
2resumed 1resumed 2resumed 1resumed 2resumed 1resumed
2resumed 1resumed 2resumed 1resumed 2resumed 1resumed
2resumed 1resumed 2resumed 1resumed 2resumed 1resumed
2resumed 1resumed 2resumed 1resumed 2resumed 1resumed
2resumed 1resumed 2resumed 1resumed 2resumed 1resumed 2
```

？？

```(lambda (x)
(display "coroutine 2")
(resume cor1 x) ;----------------------- (3)
(display "resumed 2"))
```

letrec 内部的 (cor1 "HI1") 执行完了之后，(cor2 "HI1") 使得控 制到达 (3)，显示 "resume 2". 接着 cor2 会返回。

cor2 返回到哪里？ 这是一个关键问题。是返回到 letrec, 然后

例2: 傻子计数器

```(letrec ((timer (coroutine dummy
(let loop ((tick 0))
(if (> tick 5)
(resume controller #f)  ;---------- (1)
(begin
(resume controller tick)
(loop (+ tick 1)))))))

(controller (coroutine c
(let loop ((count 0))
(if (< count c)
(begin
(display (resume timer 'go)) ;----(2)
(loop (+ 1 count))))))))
(controller 8)
)
```

controller 继续 (resume timer 'go)，使得控制返回到 (1)，这时 (resume controller #f) 已经执行完毕，而 tick > 5, 所以 timer 应该返回。

```;;; correct version
(letrec ((timer (coroutine dummy
(let loop ((tick 0))
(begin
(if (> tick 5)
(set! tick 5))
(resume controller tick))
(loop (+ tick 1)))))

(controller (coroutine c
(let loop ((count 0))
(if (< count c)
(begin
(display (resume timer 'go))
(loop (+ 1 count))))))))
(controller 8)
)
```