Взаимодействие с Java и обзор ClojureScript
Используем мощь JVM из Clojure и узнаём, как тот же язык работает в браузере.
Java interop — встроенный синтаксис Clojure для вызова методов, конструкторов и полей классов Java напрямую.
Почему interop важен
Clojure не пытается переписать весь мир. Огромная экосистема Java — работа с датами, сетью, криптографией, базами данных — доступна прямо из Clojure. Это одна из причин выбрать его для бэкенда: зрелые библиотеки уже есть.
Синтаксис interop
Есть несколько форм. Вызов метода — точка перед именем метода; создание объекта — new или точка после имени класса; статический член — слэш.
; вызов метода объекта: (.метод объект аргументы)
(.toUpperCase "clojure") ; => "CLOJURE"
(.length "привет") ; => 6
; статический метод: (Класс/метод аргументы)
(Math/sqrt 144) ; => 12.0
(Math/max 7 12) ; => 12
; создание объекта: (new Класс) или (Класс. аргументы)
(new java.util.Random) ; => объект Random
(java.util.ArrayList.) ; => пустой ArrayListВывод:
"CLOJURE" 6 12.0 12
Цепочки вызовов
Для нескольких вызовов по объекту удобен макрос doto или уже знакомый ->:
; doto вызывает методы по одному объекту и возвращает сам объект
(doto (java.util.ArrayList.)
(.add "a")
(.add "b"))
; => ArrayList ["a", "b"]ClojureScript: тот же язык в браузере
ClojureScript — это Clojure, который компилируется не в байт-код JVM, а в JavaScript. Вы пишете на том же языке (те же неизменяемые структуры, функции, макросы), но код исполняется в браузере или Node.js. Так одна команда может писать и бэкенд (Clojure на JVM), и фронтенд (ClojureScript), переиспользуя логику и формат данных EDN.
| Clojure | ClojureScript | |
| Компилируется в | байт-код JVM | JavaScript |
| Где исполняется | сервер, JVM | браузер, Node.js |
| Interop | с Java | с JavaScript и DOM |
| Применение | бэкенд, обработка данных | фронтенд, SPA |
Как работает под капотом
Поскольку Clojure компилируется в байт-код JVM, его значения — это объекты JVM, а функции — классы. Поэтому interop не требует моста или сериализации: вызов Java-метода — это прямой вызов на JVM. ClojureScript использует тот же подход, но целевая платформа — JavaScript: его компилятор (через Google Closure Compiler) превращает код в оптимизированный и минимизированный JS, отсекая неиспользуемые части.
Частые ошибки
- Путать формы interop. Точка перед именем — метод объекта; слэш — статический член; точка после класса — конструктор.
- Ждать неизменяемости от Java-объектов.
ArrayListи прочие объекты Java изменяемы — за пределами Clojure-структур гарантий нет. - Думать, что ClojureScript — отдельный язык. Это тот же Clojure с другой целевой платформой и interop с JS вместо Java.
Итоги
- Java interop даёт прямой доступ ко всей экосистеме JVM из Clojure.
- Формы:
(.метод объект),(Класс/статик),(Класс.)для конструктора,dotoдля цепочек. - ClojureScript — тот же язык, компилируемый в JavaScript для браузера.
- Единый язык на бэкенде и фронтенде с общими структурами данных и EDN.