В то время как Clojure не имеет первоклассных продолжений или сопрограмм, встроенных в качестве основной функции, возможно реализовать свою собственную.
Например, core.async - это библиотека Clojure, которая реализует модель CSP (параллельные последовательные процессы). Он использует go
макрос для преобразования кода в конечный автомат. Хотя это не совсем сопрограммы как таковые, они могут быть использованы для реализации тех же шаблонов.
Существует также pulley.cps , созданный мной макрос-компилятор, который преобразует (через cps
/ cps-fn
macros) код Clojure, написанный в прямом стиле, в стиль передачи продолжения. Насколько мне известно, это самая полная программа Clojure на тему продолжения. Он поддерживает динамическое связывание, исключения, обратный вызов между собственным и преобразованным кодом (хотя продолжение не поддерживается в разных контекстах). На данный момент call-cc
поддерживаются только неудачные продолжения (то есть традиционные ), но у меня есть планы реализовать продолжения с разделителями в будущем.
Несмотря на то, что pulley.cps напрямую не предоставляет сопрограммы как таковые, call-cc
реализовать его самостоятельно относительно просто. Фактически, один из примеров - простая реализация совместной многозадачности . Это дополнительно основано на примере CSP . Есть также пример Ping-Pong , но это скорее пример оптимизации хвостовых вызовов, чем сопрограмм.
Конечно, такого рода преобразования наиболее эффективны применительно ко всей программе. К сожалению, это невозможно только с помощью макросов, которые локализованы. Тем не менее, даже локализованные преобразования могут быть очень эффективными.