История языка Clojure
Черновик статьи. Ниже — развёрнутая хронология, идеи дизайна и контекст экосистемы; отдельные главы по ClojureScript и Datomic дополнятся позже.
Краткая хронология
| Год | Событие |
|---|---|
| 2003–2006 | Rich Hickey разрабатывает Clojure в частном порядке |
| 2007 | Публичный релиз Clojure 1.0 |
| 2009 | Рост сообщества, появление Leiningen |
| 2010 | ClojureScript — компиляция в JavaScript |
| 2011 | Datomic — база данных от Rich Hickey |
| 2013 | tools.deps / deps.edn как альтернатива Leiningen |
| 2014–2018 | spec, core.async, transducers в core |
| 2019+ | Clojure 1.10–1.12, улучшения error messages |
| 2020s | Интеграция с Java 17+, GraalVM native-image для CLI |
Rich Hickey до Clojure работал над системами в C++, Java и C# — опыт подсказал, что сложность состояния (mutable shared state) дороже, чем кажется на старте проекта.
Мотивация Rich Hickey
Доклады Simple Made Easy (2011) и The Value of Values (2012) сформулировали философию языка:
- Простота (simple) — объект с малым числом переплетений; лёгкость (easy) — близость к привычному, не всегда простое.
- Неизменяемые значения упрощают reasoning в многопоточности и распределённых системах.
- Время явно: identity имеет state, которое меняется через controlled механизмы (atom, ref), а не скрытые мутации полей.
Clojure создавался как ответ на enterprise Java с наследованием, ORM-магией и implicit mutable state — при сохранении доступа к JVM-библиотекам.
Идеи дизайна
Immutable data structures
Persistent collections (vector, map, set) structurally sharing память при conj, assoc, dissoc. Старые версии данных остаются валидными для читателей — важно для concurrency и event sourcing.
(def v1 [1 2 3])
(def v2 (conj v1 4))
; v1 по-прежнему [1 2 3], v2 — [1 2 3 4]
Identity и state
| Механизм | Когда использовать |
|---|---|
| atom | Одиночное значение, swap! |
| ref | Координированные изменения в STM |
| agent | Async update с callback |
| var | Dynamic binding per thread |
ОО-модель "объект = state + identity" заменена явным разделением.
Lisp macros
Макросы трансформируют AST на этапе компиляции — язык расширяется без изменения компилятора. Примеры в core: ->, ->>, defn, when-let.
Java interop
Clojure компилируется в JVM bytecode. Вызов Java:
(java.util.UUID/randomUUID)
Interop без генерации stub-классов — любой JAR из Maven Central.
Композиция вместо наследования
Поведение собирают из функций над map/vector, protocols и multimethods — не от deep class hierarchies.
Связь с другими языками
| Язык | Связь |
|---|---|
| Common Lisp | S-expressions, macros, REPL culture |
| Scheme | Минимализм (Clojure сознательно богаче core) |
| Java | Runtime, библиотеки, hiring |
| Scala | JVM, FP (иной синтаксис, статическая типизация) |
| Haskell | Immutability, laziness (Clojure — eager по умолчанию) |
| Erlang | Идеи identity/state (Rich изучал actor model) |
Clojure не pure FP: def, atoms и host interop допускают imperative стиль там, где это оправдано.
Эволюция tooling
Leiningen (2009+)
Долгое время стандарт: lein new, lein repl, lein uberjar. project.clj — аналог build.gradle с декларативными deps.
tools.deps и Clojure CLI (2018+)
deps.edn — EDN-файл зависимостей; команды clojure -M, clojure -X, clojure -A для alias. Официальный путь для новых проектов.
nREPL и IDE
nREPL — сетевой протокол REPL; Calva (VS Code), Cursive (IntelliJ), Emacs CIDER подключаются к running process для eval buffer.
ClojureScript и фронтенд
ClojureScript (2010) — тот же синтаксис, другой host (JS engine). Компилятор генерирует JS; популярны:
- Reagent — React wrapper;
- re-frame — архитектура SPA на events/subscriptions;
- Shadow-cljs — сборка и hot reload.
Fullstack-команда может шарить clojure.spec или схемы данных между backend и frontend.
Datomic и data-oriented design
Datomic (2012) — immutable database-as-a-value, queries на Datalog, время как first-class dimension. Идеи перекликаются с immutability в языке — append-only facts, не update-in-place rows.
Не обязательна для изучения Clojure, но показывает, куда ведёт data-centric мышление автора.
Сообщество и применение
| Область | Примеры |
|---|---|
| Fintech | Системы с высокими требованиями к корректности |
| Data | ETL, streaming (Onyx, перешёл в open source heritage) |
| Dev tools | Metabase (частично Clojure stack) |
| Open source | Penpot ecosystem, библиотеки data transformation |
Вакансии меньше, чем Java, но стабильный niche; ценятся опыт JVM + функциональное мышление.
Clojure сегодня
Актуальная ветка — Clojure 1.12+ на Java 8+ (рекомендуется Temurin 17 или 21). Язык в maintenance + evolution режиме: обратная совместимость сильная, breaking changes редки.
Соседние темы для углубления:
- Первая программа — CLI, REPL, deps.edn
- О разделе — карта материалов
- Lisp — о разделе
- Java — о разделе
Что дополнится в следующих версиях статьи
- Детальная таблица релизов 1.0–1.12 с ключевыми фичами.
- Clojure CLR и Babashka (native scripting).
- Сравнение hiring и learning curve с Kotlin/Scala.
- Кейсы миграции Java → Clojure модуль за модулем.
Доклады Rich Hickey на InfoQ и Strange Loop — лучший первичный источник мотивации языка. Видео Simple Made Easy стоит посмотреть до глубокого погружения в syntax.
Дальше по разделу: первая программа · о разделе.
Второй проход — доклады и open source (черновик)
Первичные источники Rich Hickey
| Доклад | Тема |
|---|---|
| Simple Made Easy | Простота и удобство |
| The Value of Values | Immutability |
| Hammock Driven Development | REPL и обдумывание |
Видео на InfoQ и YouTube — смотреть до углубления в syntax; философия объясняет atoms и Datomic.
Заметные open source проекты
| Проект | Стек |
|---|---|
| Metabase | Clojure backend, BI |
| Penpot | ClojureScript + backend |
| clojure.core.async | CSP channels |
Вакансии с Clojure часто упоминают data-oriented backend и REPL-driven development.
Сравнение hiring: JVM языки
| Язык | Частота вакансий | Типичный контекст |
|---|---|---|
| Java/Kotlin | Высокая | Enterprise, Android |
| Scala | Средняя | Data, финтех |
| Clojure | Нишевая | Стартапы, analytics |
Clojure не цель для максимального найма — цель для JVM + FP без корпоративного boilerplate.
Rich Hickey — ключевые доклады
| Доклад | Тема |
|---|---|
| Simple Made Easy | Простота vs привычность |
| The Value of Values | Immutability и время |
| Hammock Driven Dev | REPL и глубокое мышление |
| Clojure, The Art of Abstraction | Data vs objects |
Доклады доступны на InfoQ и YouTube — полезны до синтаксиса.
Версии Clojure 1.x (выборка)
| Версия | Фича |
|---|---|
| 1.7 | Transducers |
| 1.8 | String functions, additional Java 8 interop |
| 1.9 | Spec alpha |
| 1.10 | Error messages, tap |
| 1.11 | Syntax improvements |
| 1.12 | continue evolution, JDK 17+ focus |
Обратная совместимость — сильная сторона; код 2015 часто работает на 1.12 с минимальными правками.
Clojure в индустрии (примеры)
| Компания / проект | Область |
|---|---|
| Nubank (исторически) | Fintech, масштаб |
| Metabase | Analytics OSS |
| Pitch | Presentation software |
| Roam Research (частично) | Knowledge graph |
Список иллюстративный — проверяйте актуальность стека перед интервью.
От Lisp к Clojure
Common Lisp и Scheme дали:
- homoiconicity (код = данные);
- macro system;
- REPL culture.
Clojure отбросил mutable state OO, CLOS-style ОО и legacy syntax — pragmatic FP на JVM.
Babashka и scripting (2020+)
Babashka — native Clojure interpreter на GraalVM для быстрых CLI-скриптов без JVM cold start:
bb -e '(println (+ 1 2))'
Подходит для CI tasks, замены bash glue с доступом к Clojure stdlib. Не заменяет полноценный JVM backend с hot reload nREPL.
Clojure CLR (кратко)
ClojureCLR — порт на .NET CLR. Niche; основной путь — JVM + ClojureScript. Упоминается для команд с mixed .NET/Java инфраструктурой.
Spec, Malli и контракты
После clojure.spec (1.9) сообщество добавило Malli, Schema — валидация на границах API. Идея Rich Hickey: runtime checks + generative tests вместо тяжёлой статической системы типов.
GraalVM native-image
Компиляция uberjar в native binary уменьшает startup time для serverless и CLI. Trade-off: reflection config, longer build. Актуально для Clojure 1.11+ и Java 17.
Хронология для запоминания
2007 Clojure 1.0 → 2010 ClojureScript → 2012 Datomic → 2018 deps.edn → 2020s Babashka
Чек-лист после истории
- Понятна разница identity/state/value
- Названы atom, ref, agent
- Объяснено, зачем JVM host
- Прочитан план первой программы
Дальше: первая программа · о разделе.
Доклады Rich Hickey (что смотреть)
| Доклад | Тема |
|---|---|
| Simple Made Easy | Простота vs привычность |
| The Value of Values | Immutability |
| Hammock Driven Dev | REPL и thinking time |
Видео на InfoQ — контекст перед синтаксисом.
Сравнение hiring: Clojure, Kotlin, Scala
| Clojure | Kotlin | Scala | |
|---|---|---|---|
| JVM jobs | Niche | Android + backend | Enterprise + data |
| FP | Core | Optional | Hybrid |
| Syntax | Lisp | Java-like | Scala |
Clojure — сознательный выбор data-oriented команд, не mass market.
Упражнения
- Timeline 2007–2025 на одной странице.
- Объясните atom vs ref своими словами.
- Найдите Metabase или Penpot Clojure usage.
- Сравните
conjна vector и list. - Прочитайте
Simple Made Easysummary. - Связь с Erlang/Elixir actors.
- Babashka one-liner
bb -e '(+ 1 2)'. - Почему no
nilpunning in Clojure maps? - Java interop example без wrapper generation.
- Next: 7.md REPL practice.
FAQ
Rich Hickey still active? Clojure evolution continues; Datomic separate company.
Clojure 1.12 features? Better errors, continued host interop.
Why no classes? Protocols, records, multimethods instead.
ClojureScript same language? Same semantics, different host.
Learning curve? Parentheses + immutability; Java libs help.
IDE mandatory? REPL enough; Calva improves UX.
Breaking legacy? Strong backward compatibility culture.
Open source examples? Metabase, re-frame apps on GitHub.
Next after history? 7.md, intro.md.
Community Slack/Discord? Clojurians Slack — основной чат сообщества.
Rich Hickey до Clojure
До языка Hickey работал над системами на C++, Java, C#, Perl — опыт показал, что скрытое shared mutable state дороже, чем кажется. Clojure — ответ на complexity of state, не на нехватку скобок.
Clojure и Elixir (концептуально)
| Идея | Clojure | Elixir |
|---|---|---|
| Immutability | Persistent collections | Immutable data |
| Concurrency | STM, core.async | OTP actors |
| Host | JVM | BEAM |
Параллельное чтение: Elixir intro.
Упражнения (история)
- Timeline на одной странице 2007–2025.
- Три тезиса из Simple Made Easy.
- Пример Java interop без wrapper.
- Сравните atom и ref одним предложением каждый.
- Найдите open source проект на Clojure на GitHub.