Sebbene Clojure non abbia continuazioni di prima classe o coroutine incorporate come funzionalità di base, è possibile implementarle da sole.
Ad esempio, core.async è una libreria Clojure che implementa il modello CSP (Concurrent Sequential Processes). Usa una macro go
per trasformare il codice all'interno di una macchina a stati. Sebbene non sia esattamente coroutine di per sé, può essere utilizzato per implementare gli stessi schemi.
C'è anche pulley.cps , un compilatore di macro che ho scritto che trasforma (tramite cps
/ cps-fn
macros) Clojure codice scritto in stile diretto in stile passaggio continuo. Per quanto ne so, è il programma Clojure a continuazione più completo. Supporta l'associazione dinamica, le eccezioni, il richiamo tra codice nativo e codice trasformato (sebbene la continuazione non sia mantenuta in tutti i contesti). Al momento, sono supportate solo continuazioni abortive (ad esempio call-cc
tradizionale), ma ho in programma di implementare continuazioni delimitate in futuro.
Mentre pulley.cps non fornisce direttamente le coroutine di per sé, con call-cc
è relativamente semplice implementare la tua. In effetti, uno degli esempi è una semplice implementazione di multitasking cooperativo . Questo è ulteriormente sviluppato nell'esempio CSP . C'è anche un esempio Ping-Pong , ma è più un esempio di ottimizzazione della coda di chiamata rispetto alle coroutine.
Naturalmente, questi tipi di trasformazioni sono più efficaci se applicati all'intero programma. Sfortunatamente, questo non è possibile con le sole macro, che sono localizzate. Tuttavia, anche le trasformazioni localizzate possono essere molto efficaci.