:std/coroutine library provides support for continuation-based and thread-based coroutines.
Continuation-based coroutines are created with
coroutine, while thread-based coroutines are
cothread. Both types of coroutine are resumed with
continue and yield results
Continuation-based coroutines are more lightweight, but by virtue of implementation they cannot
yield inside finalizer blocks.
Thread-based coroutines are more heavyweight, but don't suffer from this problem as they have
a delimited dynamic scope.
(coroutine proc arg ...) proc := procedure => <coroutine>
Creates a new coroutine that evaluates proc with arguments
(proc arg ...).
The coroutine is initially a suspended continuation, and can be resumed
(coroutine? obj) => boolean
Returns true if the object is a coroutine.
(cothread proc arg ...) proc := procedure => <cothread>
Creates a new cothread that evaluates proc with arguments
(proc arg ...).
The thread is initially suspended, and can be resumed with
(cothread? obj) => boolean
Returns true if the object is a cothread.
(continue co arg ...) co := coroutine or cothread => any
Resumes the coroutine or cothread, with the arguments becoming the values of the last yield. If the continuable was in initial suspended state, then it is resumed and the arguments are ignored.
(yield arg ...)
Continues execution of the main routine or thread, with the arguments becoming the values of the last continue.
(cothread-stop! co) co := cothread
Stops the execution of a cothread.
Here is a coroutine that iterates from 1 to n, yielding them as values and ending the generation
with the symbol
(def (1-to-n n) (let lp ((i 1)) (when (<= i n) (yield i) (lp (1+ i)))) 'end) ;; iterate through the values yielded by the coroutine (let (cort (coroutine 1-to-n 10)) (let lp () (let (next (continue cort)) (unless (eq? next 'end) (displayln next) (lp))))) ;; displays: 1 2 3 4 5 6 7 8 9 10