Конкурентность core.async и место Clojure среди ФП
Финальный урок: каналы core.async, сравнение с другими функциональными языками и итог по Lisp-мышлению.
core.async — библиотека Clojure для конкурентности через каналы: независимые процессы общаются, передавая значения по каналам, а не разделяя память.
Конкурентность через каналы
Помимо atom/ref/agent у Clojure есть ещё один подход к параллелизму — каналы из библиотеки core.async, вдохновлённые моделью CSP (как в языке Go). Идея: вместо общей изменяемой памяти процессы передают сообщения по каналам. Один кладёт значение в канал, другой забирает.
; идея core.async (обзорно):
; (def ch (chan)) ; создать канал
; (go (>! ch "привет")) ; в фоне положить значение
; (go (println (<! ch))) ; в фоне забрать и напечатать
; >! кладёт в канал, <! забирает; go запускает лёгкий процессБлок go запускает лёгкий «зелёный» процесс, который не блокирует поток JVM. Это удобно для конвейеров обработки, очередей задач и координации множества асинхронных операций без ручного управления потоками.
Два взгляда на параллелизм в Clojure
| Подход | Идея | Когда |
| atom / ref / agent | разделяемое состояние под защитой | общее изменяемое состояние |
| core.async (каналы) | обмен сообщениями, без общей памяти | конвейеры, координация задач |
Clojure среди функциональных языков
Сравним Clojure с двумя другими известными ФП-языками, чтобы понять его нишу.
| Clojure | Haskell | Scala | |
| Типизация | динамическая | статическая, строгая | статическая |
| Чистота | прагматичная (эффекты разрешены) | чистая, эффекты в монадах | смешанная |
| Парадигма | ФП + Lisp-макросы | чистое ФП | ФП + ООП |
| Платформа | JVM | своя (GHC) | JVM |
Haskell жёстко требует чистоты: побочные эффекты выражаются через типы и монады, лень включена по умолчанию. Clojure прагматичнее — эффекты разрешены, лень точечная. Scala совмещает ООП и ФП с богатой системой типов, но синтаксис обычный, не Lisp. Уникальность Clojure — гомоиконность и макросы: язык можно расширять изнутри, чего не дают ни Haskell, ни Scala.
Почему Lisp и неизменяемость — итог курса
За курс мы прошли путь от страха перед скобками до написания собственных макросов. Главные идеи, которые делают Clojure особенным:
- Lisp-мышление: код — это данные, поэтому язык расширяем макросами под вашу задачу.
- Неизменяемость по умолчанию: данные нельзя испортить, поэтому конкурентность безопасна, а рассуждать о коде проще.
- Данные как данные: простые map и vector вместо классов, единые инструменты для всего.
Где применяют Clojure
Эти свойства делают язык сильным в задачах, где важна надёжность и гибкость: бэкенд и API, обработка данных и ETL, стартапы, где маленькая команда быстро меняет продукт. А через ClojureScript тот же язык покрывает и фронтенд.
Частые ошибки
- Считать core.async единственным способом конкурентности. Часто atom или ref проще; каналы нужны для конвейеров и координации.
- Сравнивать языки как «лучше/хуже». У Haskell, Scala и Clojure разные сильные стороны; Clojure выбирают за неизменяемость, JVM и макросы.
- Бросить REPL после курса. Lisp-мышление развивается именно в интерактивной работе — продолжайте экспериментировать в REPL.
Итоги
- core.async даёт конкурентность через каналы (модель CSP) и лёгкие процессы
go. - Это дополняет atom/ref/agent: каналы — для обмена сообщениями без общей памяти.
- Среди ФП Clojure выделяется динамикой, прагматизмом и уникальными макросами.
- Lisp-мышление и неизменяемость — главные причины выбрать Clojure для бэкенда, данных и стартапов.