I started to implement a Concurrent ML (CML) and read about the actor model as part of Gambit termite library. I feel like the termite will force me into a certain way to handle errors: exceptions will be "propagated" to linked termite's process, if the program does not rely on exceptions, you still have room for programming errors. It seems to me coop is more like Scheme. Scheme offers several tools to handle errors (raise, maybe, values) but does not force a particular style. I used to think it gives room to experiment, and because I was locked in world where exceptions are not cheap, I used to prefer to rely on exception only when the error need to propagate such as the caller does not necessarily need to handle it, and pass it up around or up the stack manually. One case where I do not use exceptions is input validation: I consider the user to be wise to check the return value if they call the validation procedure (in other words, the user does not call validation needlessly!). Anyway, at the moment it seems to me CML is more like Scheme where it provides the tool but does not lock into a given style of programming. I have no proof yet, it seems possible to implement SRFI-18 [0] and the actor model with CML on top of coop. Here is clue where make-thread and thread-join are implemented with coop: (define (make-thread thunk) (define channel (make-coop-channel)) (coop-spawn (lambda () (thunk) (coop-apply (coop-produce channel #t)))) channel) (define (thread-join channel) (coop-apply (coop-consume channel))) (define channel (make-thread (lambda () 42))) (thread-join channel) [0] https://srfi.schemers.org/srfi-18/ coop is general enough to work for inter-process and intra-process communication. async / await syntax or procedure are not necessary, and non-blocking ports, generator, or accumulator can rely on an event-loop. In other words, coop is not necessarily bound to a particular implementation of non-blocking procedures. In coop, coop-spawn may start inside the current process, then when coop-priority is set to +inf.0, it may move parallel computation (that is my understanding of the behavior of gochans). Still, coop-priority might be completely ignored by the host, and a flow would need to be started in parallel thread explicitly. Coop is supposed to work in the following situation: (define channel (make-coop-channel)) (make-thread (lambda () (coop-apply (coop-produce channel 42))) (coop-apply (coop-consume channel)) ;; => 42 In other words, coop may be implemented in many thread models relying on POSIX threads or multiple POSIX processus, multiple interpreters, etc... The specification does specify what objects can be passed in a channel, it is expected that at least readable types can go through. The behavior of parameters are not necessarily changed, since the only seemingly parameter looking procedure is coop-priority that is only a hint. Checkout the short preliminary SRFI at https://github.com/pre-srfi/coop#specification