Clojure
(require '[next.jdbc :as jdbc])
Увага: у Clojure порожня колекція не виступає як false.
- простих web routes;
- REST API;
- Ring applications;
- internal tools;
- невеликих backend-сервісів. ch "hello"))
- pure functions;
- data transformations;
- API handlers;
- business rules;
- regression checks;
- integration tests;
- REPL-driven verification. `future`:
</syntaxhighlight>
Безпека Clojure-застосунків
Приклад: Pedestal застосовується для для:
Maven dependencies
Atom — механізм для синхронної, незалежної зміни стану. * immutable facts;
- time-aware database;
- Datalog queries;
- historical data;
- auditability;
- data as values;
- entity-attribute-value model. :headers {"Content-Type" "text/plain"}
Приклад dependency: </syntaxhighlight> Приклади:
(future
Refs використовуються з Software Transactional Memory або STM. Основні інструменти для state: (fn [x] (* x x))
@counter
критично: logging у Clojure-системах має бути структурованим і не повинен розкривати secrets або персональні інформаційні дані. `cond`:
== Re-frame ==
Приклад створення об’єкта:
Sets використовуються для:
</syntaxhighlight>
Clojure має кілька умовних форм.Практична роль: ці інструменти дають прості моделі для async, lazy і coordinated computation. (require '[clojure.spec.alpha :as s])
(str "User: " (:name x)))
</div>
ClojureScript застосовується для для:
{:status 200
(java.util.Date.)
'''Namespace''' організовує код і контролює імена. :age 25
(println (async/<! ch)))
`deps.edn` описує:
критично: Clojure не каже “стану не існує”. Головна думка: Clojure — це мова для тих. * atoms;
- refs;
- agents;
- vars;
- delays;
- promises;
- futures.== Clojure і Common Lisp ==
Clojure здатна використовувати Maven-залежності. :where </syntaxhighlight>
:age 25
<syntaxhighlight lang="clojure">
Основні елементи:
Приклад:
<div style="background:#eef2ff; border-left:6px solid #4f46e5; padding:12px; margin:12px 0;">
<div style="background:#fff7ed; border-left:6px solid #fb923c; padding:12px; margin:12px 0;">
</div>
<syntaxhighlight lang="clojure">
* локального mutable state;
* counters;
* caches;
* runtime configuration;
* shared state з atomic updates;
* простих stateful компонентів. * Документація Reitit.== Agents ==
<syntaxhighlight lang="clojure">
'''критично:''' круглі дужки в Clojure зазвичай означають не “групування”, а виклик функції або special form. (s/def ::user (s/keys :req [::name ::age]))
'''Перевага JVM-екосистеми:''' Clojure здатна підключати як Clojure-бібліотеки, так і Java-бібліотеки з Maven-світу. (GET "/" [] "Hello"))
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
(map #(* % 10))
</div>
Ring — базова web abstraction у Clojure. ! roles :admin) </syntaxhighlight> Приклад Java interop:
(defmulti describe :type)
</div>
(update :age inc)))
</div>
'''next.jdbc''' — сучасна бібліотека для роботи з SQL-базами в Clojure. (str "Hello, " "world")
(get user :age)
<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
(def roles #{:admin :user :manager})
== next.jdbc ==
discount-value (* subtotal discount)]
Можливі складнощі:
Refs корисні, коли потрібно координовано змінити кілька значень у транзакції. !== Приватність даних ==
<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
'''Практична роль:''' Reagent робить React-розробку ближчою до Clojure-підходу: UI як інформаційні дані й функції.
Практична роль: records корисні там, де простих maps недостатньо й потрібен окремий тип. {:name "Alice"
(defn handler [request]
Поширені підходи:
- data-driven routes;
- coercion;
- Swagger/OpenAPI;
- middleware;
- frontend і backend routing;
- nested routes;
- performance-oriented routing. * Документація Compojure.
</syntaxhighlight> Практична роль: keywords виступає як основним способом іменування полів у Clojure-даних. Це означає виклик функції `+` з аргументами `1`, `2`, `3`. Clojure
Spec
Практична порада: Clojure варто обирати, коли команда готова працювати з функціональним data-oriented підходом і хоче використовувати JVM. Приклад функції:
(str "Order: " (:id x)))
Функції вищого порядку дозволяють:
- numbers;
- strings;
- booleans;
- nil;
- keywords;
- symbols;
- lists;
- vectors;
- maps;
- sets. Datomic — база даних, тісно пов’язана з Clojure-екосистемою. (require '[compojure.core :refer [defroutes GET]])
Re-frame — framework для ClojureScript frontend-застосунків поверх Reagent. (assoc :role :admin)
Clojure і Java
Nil і booleans
Futures, delays і promises
Malli
- web applications;
- middleware;
- HTTP handlers;
- REST API;
- routing libraries;
- server integration. Практична роль: destructuring робить роботу з maps і vectors компактною й читабельною.
</syntaxhighlight> Потрібно контролювати: У Clojure інформаційні дані за замовчуванням immutable. Вона добре підходить для backend-систем, інтеграцій, data processing, фінансових застосунків, DSL, ClojureScript frontend і складних доменних моделей. Agents корисні для:
{:name "Carol" :role :user}])
Перша програма на Clojure
{:name "Alice"
Практична роль: STM дає можливість безпечніше координувати кілька пов’язаних змін стану.(if true "yes" "no") Clojure застосовується для для web development, хоча зазвичай не через один монолітний framework, а через набір бібліотек. (str/lower-case (str/trim text))) Практична роль: Reitit часто обирають для сучасних Clojure API через data-driven підхід і хорошу інтеграцію зі схемами. * Clojure libraries;
- Java libraries;
- Maven Central;
- private Maven repositories;
- enterprise artifacts;
- JVM tooling.== Коли Clojure здатна бути невдалим вибором ==
!=== оновлення версій map ===
== Reitit ==
'''Практична роль:''' Leiningen довго був стандартним інструментом для Clojure-проєктів і досі часто зустрічається в existing codebase. * писати маленькі pure functions;
* моделювати домен простими maps і values;
* використовувати REPL для дослідження;
* уникати зайвих macros;
* не зловживати global defs;
* використовувати `let` для локальних значень;
* писати тести для data transformations;
* структурувати namespaces;
* не приховувати складну логіку в threading macros;
* використовувати spec або Malli для важливих boundary;
* контролювати lazy sequences;
* документувати public functions;
* обмежувати mutable state atoms/refs/agents;
* використовувати Java interop обережно. Усе інше вважається truthy, включно з `0`, порожнім рядком і порожньою колекцією. Вона каже: стан має бути контрольованим, явним і відокремленим від чистих функцій.<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
== Logging ==
[?e :user/name ?name]]
lein run Vector — впорядкована indexed collection. ! * single app-db;
- events;
- subscriptions;
- effects;
- coeffects;
- pure functions;
- reactive data flow. Приклад:
Printable
Приклад:
(is (= 5 (core/add 2 3)))))
Приклад:
- validation;
- schema definitions;
- coercion;
- API validation;
- documentation;
- data-driven specs;
- frontend і backend shared schemas. (take 5 (range))
(def p (promise))
<syntaxhighlight lang="clojure">
* composable SQL;
* dynamic queries;
* query generation;
* data-driven database access;
* зменшення string concatenation у SQL. Python
== Leiningen ==
(do ~@body)))
Основні структури:
== Web development ==
=== Простий Ring handler ===
:from [:users]
'''Sequence abstraction''' — одна з ключових ідей Clojure. (def numbers [1 2 3 4 5])
Protocols використовуються для:
Результат буде `"truthy"`. (+ 40 2)))
'''Суть Clojure-коду:''' програми будуються як композиція функцій, які приймають інформаційні дані й повертають нові інформаційні дані. datasource ["select * from users"])
</div>
'''Практична роль:''' Clojure добре підходить для тестування, бо багато логіки можна оформити як чисті функції над даними. '''Macro''' у Clojure дає можливість перетворювати код до виконання.<syntaxhighlight lang="clojure">
<div style="background:#eef2ff; border-left:6px solid #4f46e5; padding:12px; margin:12px 0;">
(:require [clojure.string :as str]))
Приклад:
<syntaxhighlight lang="clojure">
'''Практична роль:''' ClojureScript дає можливість використовувати Clojure-підхід у браузері й будувати frontend у функціональному стилі. False-like значення:
(str "Hello, " name))
`when`:
(defprotocol Printable
Вони допомагають організувати:
(println "computing")
:body "Hello from Ring"})`let` створює локальні bindings.
Lists
Map — key-value структура.== REPL == (def counter (atom 0))
'''Головне правило:''' хороший Clojure-код має бути простим, data-oriented, функціональним і зрозумілим у REPL. Clojure має сильну взаємодію з Java. '''Головна перевага:''' Clojure дає можливість моделювати систему як перетворення даних, а не як мережу mutable objects. (- subtotal discount-value)))
Приклад:
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
</div>
(println (greet "Alice"))
'''Pedestal''' — web framework і набір інструментів для Clojure services.== Records ==
:else "unknown")
Виклик:
'''ClojureScript''' — це варіант Clojure, який компілюється в JavaScript. '''Висновок:''' Scala робить ставку на статичну типізацію й type system, а Clojure — на прості інформаційні дані, runtime-гнучкість і REPL. Scala
{:deps {org.clojure/clojure {:mvn/version "1.11.1"}}
:where [:= :active true]}
== Macros ==
</div>
Clojure дає компактність, гнучкість, потужні macros, persistent data structures і доступ до JVM-екосистеми.<syntaxhighlight lang="clojure">
== Хороші практики Clojure ==
'''Практична роль:''' Pedestal підходить для складніших backend-сервісів, де потрібен interceptor-based pipeline.</div>
== Ring ==
Clojure і Scala
Висновок: Python універсальніший і популярніший, а Clojure сильніша там, де потрібні JVM, immutable data й REPL-driven functional design. (map inc [1 2 3]) (println "Hello, world!")
Приклад:
(contains?42))
Lazy sequences
Sequences
'''Compojure''' — routing library для Ring.{{SEO
|title=Clojure — функціональна мова програмування для JVM, Lisp, immutable data, concurrency і backend-систем
|description=Clojure — Wiki-стаття про сучасну функціональну Lisp-мову програмування для JVM. Розглянуто синтаксис Clojure, REPL, immutable data structures, functions, macros, namespaces, Leiningen, deps.edn, Maven, JVM, Java interop, atoms, refs, agents, core.async, Ring, Compojure, Re-frame, Datomic, переваги, обмеження і хороші практики.
|keywords=Clojure, мова програмування Clojure, Clojure programming language, Lisp, JVM, functional programming, immutable data, persistent data structures, REPL, macros, namespaces, Leiningen, deps.edn, Java interop, atoms, refs, agents, STM, core.async, Ring, Compojure, Re-frame, Datomic, backend, concurrency, програмування
|alternativeTo=verbose Java-код; mutable state у backend-системах; складні об’єктні ієрархії; ручна синхронізація потоків; менш виразні JVM-мови для функціонального програмування; скриптові рішення без JVM-екосистеми; складні enterprise-системи без REPL-driven development
}}
== Multimethods ==
* backend development;
* JVM applications;
* web services;
* API;
* data processing;
* financial systems;
* event-driven systems;
* distributed systems;
* scripting на JVM;
* DSL;
* REPL-driven development;
* інтеграцій з Java;
* concurrent systems;
* frontend через ClojureScript;
* full-stack функціональних застосунків. Приклад:
{| class="wikitable"
'''Reagent''' — ClojureScript wrapper для React. {:deps {cheshire/cheshire {:mvn/version "5.12.0"}}}
Clojure має threading macros для читабельних pipelines. через JVM Clojure отримує:
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
'''List''' у Clojure записується в круглих дужках.== Sets ==
оновлення версій map:
</div>
Приклад:
(defroutes app
(def user {:name "Alice" :age 25})
<syntaxhighlight lang="clojure">
</div>
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
</div>
(:name user)
(def log-state (agent []))
'''Помилка:''' сприймати Clojure як Java з дужками.<div style="background:#ecfdf5; border-left:6px solid #10b981; padding:12px; margin:12px 0;">
(defn total-price [{:keys [price quantity discount]}]
Приклад:
[:div "Hello from Reagent"])
(filter even? [{:name "Alice" :role :admin}
- `defn` створює функцію;
- `str` об’єднує рядки;
- `println` виводить результат;
- аргументи функції записуються у векторі `[name]`. (send log-state conj "event")
Clojure застосовується для для:
:headers {"Content-Type" "text/plain"}
</syntaxhighlight>
- web services;
- interceptors;
- API;
- long-running services;
- enterprise backend;
- data-driven request processing. lein new app my-app
Тематичні мітки
Без quote Clojure сприймає список як виклик функції:
- сортування зберігає кількість елементів;
- encode/decode повертає початкове значення;
- сума не залежить від порядку елементів;
- функція не падає на валідних input.</syntaxhighlight>
<div style="background:#e8f8f5; border-left:6px solid #16a085; padding:12px; margin:12px 0;">
(+ a b))
(group-by :role users)
"Alice"
(async/go
Приклад handler:
`assoc` створює нову map, а не змінює стару. Clojure має вбудовану бібліотеку `clojure.test`.== конкурентні переваги Clojure ==
'''Multimethod''' дає можливість обирати реалізацію функції за результатом dispatch-функції. * Документація core.async. (async/>! Clojure
</div>
'''Практична роль:''' Compojure — класичний легкий спосіб описувати маршрути в Clojure web applications. Потрібно розуміти, коли потрібен agent, atom, core.async або інший підхід.
REPL дає можливість:
Reagent застосовується для для:
Map destructuring:
Практична порада: SQL як інформаційні дані здатна бути зручним, але складні запити все одно потрібно читати, тестувати й оптимізувати як SQL.'''Небезпека:''' Clojure дає можливість писати дуже компактний код, але надмірна компактність здатна зробити логіку важкою для читання. '''Суть прикладу:''' Clojure-код складається з виразів, які обчислюються й повертають значення. це сучасна функціональна мова програмування з родини Lisp, яка функціонує переважно на '''JVM''' і орієнтована на immutable data, простоту моделей даних, REPL-driven development, concurrency і практичну розробку складних систем виступає ключовою рисою '''Clojure'''. Приклад:
</div>
<syntaxhighlight lang="clojure">
</div>
Функції виступає як основою Clojure. Критерій
Приклад:
Приклад:
:age 25
Приклади властивостей:
- `false`;
- `nil`. ! (defn hello []
(ns my-app.core
(str name " is " age))
{| class="wikitable"
(str name " is " age))
== State management ==
</div>
'''Практична роль:''' vectors виступає як однією з найчастіших структур Clojure для впорядкованих даних. застосовується для для:
(reduce +))
[my-app.core :as core]))
Результат:
updated-user
deps.edn і Clojure CLI
(update :age inc)) :active true})
- name
- асинхронних оновлень;
- background state transitions;
- serialized updates;
- event processing;
- незалежних stateful об’єктів.
<div style="background:#ecfdf5; border-left:6px solid #10b981; padding:12px; margin:12px 0;"> (update user :age inc) '''Практична роль:''' Re-frame дає структурований підхід до великих ClojureScript frontend-застосунків.
</div>
(def app-name "My App")
</syntaxhighlight> Суть persistent structures: нова реліз системи даних створюється ефективно для бізнесу, без повного копіювання всієї структури в типових випадках. (->> [1 2 3 4 5]
(def users
критично: синтаксис Clojure здатна виглядати незвично через дужки, але його регулярність виступає як однією з причин сили мови.|-
| Платформа
| JVM
| JVM, Android, multiplatform
|-
| Типізація
| Динамічна
| Статична
|-
| Стиль
| Lisp, functional, data-oriented
| Pragmatic OOP/FP
|-
| Android
| Не основна ніша
| Сильна ніша
|-
| Enterprise adoption
| Нішевіша
| Ширша для Java-команд
|}
Clojure-застосунки мають звичайні security-ризики JVM і web-систем. У цьому прикладі:
У функції:
'''Перевага Java interop:''' Clojure здатна використовувати готові Java SDK, frameworks і libraries без окремого bridge-шару. `let` корисний для:
(def user
Atoms використовуються для:
Основні конкурентні переваги Clojure:
(def expensive
Приклад:
<syntaxhighlight lang="clojure">
{| class="wikitable"
'''Практична роль:''' Datomic добре поєднується з Clojure-філософією immutable data і data-oriented design. (def result
(async/go
core.async
- lists;
- vectors;
- maps;
- sets;
- lazy sequences;
- ranges;
- file lines;
- generated data. * створення проєктів;
- запуску REPL;
- керування dependencies;
- запуску тестів;
- packaging;
- deployment;
- створення uberjar.
(add 2 3) Clojure-екосистема підтримує property-based testing, зокрема через test.check. :user/status
Вектори часто використовуються для:
</syntaxhighlight>
(defmethod describe :user [x]
Re-frame базується на: Приклад: Критично: macros дуже потужні, але їх варто писати лише тоді, коли звичайних функцій недостатньо. Вона не робить акцент на класичній об’єктній моделі, а пропонує будувати програми через функції, immutable data structures, namespaces, protocols, multimethods і macros. (map #(* % 10)) 5 Records використовуються для: Set — колекція унікальних значень. core.async — бібліотека для асинхронного програмування через channels. (defrecord User [name]
age 25]
Clojure і Python обидві динамічні, але мають різні ніші. Clojure належить до родини Lisp. (s/def ::name string?)
Vars і def
Приклад:
Увага: agents підходять не для будь-якої concurrency-задачі.Сучасний Clojure часто використовує Clojure CLI і файл `deps.edn`. Це критично для умов і перевірок. Приклад ідеї:
(def updated-user (jdbc/execute! Критерій (def ch (async/chan)) Практична роль: `map`, `filter`, `reduce` і подібні функції виступає як щоденними інструментами Clojure-розробника. Приклад:
</syntaxhighlight> Анонімна функція: (dissoc user :active) Reitit підтримує:
(defn greet [name]
Leiningen — класичний build tool для Clojure.</syntaxhighlight>
Namespaces використовуються для:
(cond (-> {:name "Alice" :age 25} (defn handler [request] </syntaxhighlight> (defn add [a b]
* проміжних значень;
* читабельності;
* локального scope;
* уникнення дублювання;
* розбиття складної логіки. core.async застосовується для для:
(println "Active"))
Clojure добре підходить для:
<syntaxhighlight lang="clojure">
If, when і cond
Приклад:
* validation;
* data contracts;
* генерації тестових даних;
* documentation;
* runtime checks;
* API boundaries. Clojure
<div style="background:#e8f8f5; border-left:6px solid #16a085; padding:12px; margin:12px 0;">
</div>
<div style="background:#fff7ed; border-left:6px solid #fb923c; padding:12px; margin:12px 0;">
Malli застосовується для для:
`if`:
`delay`:
Clojure macros можливі тому, що код має структуру даних. (assoc user :age 26)
(print-value [x]))
== Keywords ==
(def account-b (ref 50))
</div>
Приклад ідеї:
* Ring;
* Reitit або Compojure;
* Jetty або http-kit;
* next.jdbc;
* HoneySQL;
* Integrant або Component;
* Malli або spec;
* Timbre або tools.logging;
* PostgreSQL;
* Kafka або інші message systems. Ефективний Clojure-код потребує іншого мислення: інформаційні дані, функції, immutability і REPL. * Матеріали щодо functional programming, immutable data, REPL-driven development і JVM interop. (filter even?)
(let [[a b c] [1 2 3]]
'''Record''' створює іменований тип, схожий на map, але з додатковими можливостями. @expensive
* dependencies;
* aliases;
* paths;
* tools;
* test конфігурації;
* REPL startup;
* build tasks. (str "Hello, " name))
(delay
<syntaxhighlight lang="clojure">
* списки `(...)`;
* вектори `[...]`;
* maps `{...}`;
* sets `#{...}`;
* symbols;
* keywords;
* functions;
* special forms;
* macros. Валідація, доступи, secrets і залежності мають перевірятися окремо. Kotlin
'''Перевага:''' Clojure дає можливість писати компактний, композиційний і гнучкий код, зберігаючи доступ до Java-бібліотек і JVM-інфраструктури. '''Clojure''' — це сучасна функціональна Lisp-мова для JVM, яка робить акцент на immutable data, простих структурах, REPL-driven development, Java interop і data-oriented design. '''Keyword''' — це іменоване значення, яке часто застосовують, коли потрібно як ключ у map.<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
</div>
user=> (+ 2 3)
(let [subtotal (* price quantity)
</syntaxhighlight>
Приклад:
#(* % %)
<div style="background:#fdecea; border-left:6px solid #e74c3c; padding:12px; margin:12px 0;">
<div style="background:#eef2ff; border-left:6px solid #4f46e5; padding:12px; margin:12px 0;">
Приклад ідеї:
<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
</div>
Приклад простого macro:
Lazy sequences корисні для:
'''Правило:''' REPL — потужний інструмент, але доступ до production REPL або live data має бути суворо контрольований.</div>
<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
(if [] "truthy" "falsey")
'''критично:''' lazy evaluation здатна бути дуже корисною, але іноді створює неочевидний час виконання або утримання ресурсів.</div>
<div style="background:#e8f8f5; border-left:6px solid #16a085; padding:12px; margin:12px 0;">
<div style="background:#fff7ed; border-left:6px solid #fb923c; padding:12px; margin:12px 0;">
(defmethod describe :default [x]
'''Висновок:''' Java краще знайома масовим enterprise-командам, а Clojure дає компактність, immutable data й REPL-driven development на JVM.<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
<syntaxhighlight lang="clojure">
<syntaxhighlight lang="text">
(def updated-user (assoc user :age 26))
<syntaxhighlight lang="text">
</div>
"Unknown")
== Property-based testing ==
Приклад ідеї:
Clojure має невелику кількість синтаксичних форм.=== Обробка списку ===
(assoc :active true)
</div>
== Pedestal ==
<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
'''Destructuring''' дає можливість інтуїтивно діставати значення зі структур. '''REPL''' або '''Read-Eval-Print Loop''' — ключовий інструмент Clojure-розробки.
</syntaxhighlight> </syntaxhighlight>
(dosync
(print-value [x]
Типовий backend stack здатна включати:
Clojure і Kotlin
:paths ["src" "resources"]}
Приклади задач на Clojure
(defmacro unless [condition & body] Clojure підтримує lazy sequences — послідовності, які обчислюються поступово. Головна перевага immutability: інформаційні дані не змінюються неочікувано, тому простіше думати про стан, concurrency і тестування. Agent застосовується для для асинхронної зміни стану. Окремо варто відзначити хто хоче будувати системи навколо даних і функцій, а не навколо mutable object-ієрархій. Це означає, що при “зміні” структури створюється нова реліз системи, яка ефективно для бізнесу розділяє частину пам’яті зі старою. * Документація ClojureScript, Reagent і Re-frame. * JVM-екосистема;
- Lisp-синтаксис;
- REPL-driven development;
- immutable data structures;
- persistent data structures;
- functional programming;
- compact code;
- macros;
- Java interop;
- concurrency primitives;
- data-oriented design;
- ClojureScript;
- strong community around simplicity;
- хороша придатність для складних доменних даних;
- зручність для DSL. * message passing;
- pipelines;
- async workflows;
- coordination;
- event processing;
- CSP-style concurrency. Для функцій зазвичай використовують `defn`:
Namespaces
ClojureScript
</syntaxhighlight> (def user {:name "Alice" :age 25})
Джерела
| Для цього краще `let`. backend-сервісів забезпечується через Clojure використовують; так само реалізовано data processing, фінансових систем, web applications, інтеграцій, DSL, аналітичних інструментів, JVM-застосунків, event-driven систем і проєктів, де важлива гнучкість, композиційність і контроль стану. Macros використовуються для:
(reduce + [1 2 3 4 5])
Leiningen застосовується для для: `def` створює var у namespace.
Головна структура Clojure: maps часто виступає як основою доменних даних, API payloads, конфігурацій і проміжних результатів. Clojure </syntaxhighlight> (ns my-app.core-test Практична роль: multimethods дають гнучкий polymorphism, який не прив’язаний лише до класу об’єкта.=== Функція для бізнес-логіки === (def user (->User "Alice" 25)) Головна ідея даних: Clojure заохочує описувати домен через прості immutable data structures, а не через складні mutable objects.Atoms
Тести використовуються для: Приклад: '(1 2 3) Compojure застосовується для для: </syntaxhighlight> (str "Hello, " name)) </syntaxhighlight> (defn normalize [text] Malli — популярна бібліотека для data schemas у Clojure. (:name user) HoneySQL
HoneySQL корисний для: Приклад: Увага: хороша структура namespaces дуже важлива для підтримуваності Clojure-проєкту. ! "minor") (+ a b c)) інформаційні дані в Clojure
(import java.time.LocalDate) Практична роль: set зручний, коли важлива саме наявність значення, а не порядок.
Higher-order functionsDatomic(Math/sqrt 16)
(swap! [1 2 3 4 5])
</syntaxhighlight> </syntaxhighlight> Практична роль: property-based testing добре поєднується з Clojure, бо мова орієнтована на інформаційні дані й чисті функції.</syntaxhighlight>
Загальний SEO-опис
Reagent== Vectors ==
Практична роль: Clojure не ізольована мова — вона здатна використовувати велику JVM-екосистему й працювати поруч із Java-кодом.== JVM == Приклад literal list: Потрібно контролювати:
{:name "Alice"
Практична роль: lifecycle-бібліотеки допомагають будувати Clojure-застосунки, які інтуїтивно запускати, зупиняти й перезавантажувати в REPL. Clojure і Scala обидві працюють на JVM, але мають різну філософію. * Документація Clojure CLI і deps.edn.<syntaxhighlight lang="clojure">
:body "Hello from Clojure"})
Spec здатна використовуватися для:
</syntaxhighlight> Destructuring</syntaxhighlight> </syntaxhighlight> Багато колекцій можна опрацьовувати однаково як послідовності: (require '[clojure.core.async :as async]) Підказка: у Clojure-прикладах критично дивитися на форму даних, чистоту функцій, immutability і читабельність pipelines.(:name user) </syntaxhighlight> * боротися з дужками замість розуміння структури;
* писати Clojure як Java;
* використовувати mutable state без потреби;
* створювати занадто багато records там, де достатньо maps;
* надмірно використовувати macros;
* не розуміти lazy sequences;
* плутати `->` і `->>`;
* зловживати nested anonymous functions;
* створювати великі namespaces без структури;
* не використовувати REPL;
* не тестувати pure functions;
* ігнорувати nil;
* не валідувати external input.<syntaxhighlight lang="clojure">
Clojure активно використовує функції вищого порядку. ! '''Практична роль:''' `if` підходить для двох варіантів, `when` — для дії за умовою, `cond` — для кількох умов. (-> user
</div>
* унікальних значень;
* перевірки належності;
* ролей;
* tags;
* множинних операцій;
* фільтрації. Приклад:
</div>
'''Практична роль:''' sequence abstraction дає можливість писати універсальний код для різних типів колекцій. '''критично:''' Clojure здатна дати велику продуктивність сильній команді, але потребує культурної згоди щодо стилю, REPL і функціонального мислення.== Compojure ==
* frontend applications;
* React-based UI;
* single-page applications;
* Reagent;
* Re-frame;
* full-stack Clojure/ClojureScript systems;
* interactive web tools;
* dashboards;
* internal interfaces. counter inc)
== Функції ==
Clojure функціонує на '''Java Virtual Machine'''.</div>
* персональні інформаційні дані;
* фінансові інформаційні дані;
* logs;
* event streams;
* database records;
* API payloads;
* secrets;
* tokens;
* REPL-доступ до production;
* test fixtures;
* data dumps;
* monitoring output. (defmethod describe :order [x]
<div style="background:#ecfdf5; border-left:6px solid #10b981; padding:12px; margin:12px 0;">
Clojure розроблена як практична Lisp-мова для сучасної розробки. * Документація Leiningen. {| class="wikitable"
Виклик static method:
<syntaxhighlight lang="clojure">
(def account-a (ref 100))
* dependency vulnerabilities;
* authentication;
* authorization;
* SQL injection;
* XSS;
* CSRF;
* unsafe deserialization;
* secrets;
* logging sensitive data;
* Java interop with unsafe APIs;
* file access;
* command execution;
* API validation;
* dependency supply chain. * typed domain data;
* protocol implementations;
* Java interop;
* performance-sensitive structures;
* структур, яким потрібна ідентичність типу. * Clojure Reference. |-
| Основна платформа
| JVM
| CPython та інші runtime
|-
| Стиль
| Functional, Lisp, immutable data
| Multi-paradigm, scripting, data science
|-
| ERP-платформа
| JVM + Clojure libraries
| Дуже широка, особливо AI/Data Science
|-
| REPL
| Центральний workflow
| виступає як, але менш центральний для production
|-
| Новачкам
| Синтаксис здатна бути незвичним
| Зазвичай простіший старт
|}
== Persistent data structures ==
! * Документація clojure.test. `promise`:
<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
* простий і регулярний синтаксис;
* код як інформаційні дані;
* macros;
* зручне метапрограмування;
* гнучкі DSL;
* REPL-driven workflow;
* компактні вирази. Приклад ідеї Datalog-запиту:
</div>
</div>
@p
cd my-app
<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
== Let ==
Clojure часто порівнюють із Java. '''Reitit''' — сучасна routing library для Clojure і ClojureScript. Критерій
Clojure має обмеження. Clojure
* доступ до Java-бібліотек;
* mature runtime;
* garbage collection;
* tooling;
* monitoring;
* performance capabilities;
* deployment у Java-екосистемі;
* інтеграцію з enterprise-системами;
* доступ до Maven-репозиторіїв;
* cross-platform виконання.<syntaxhighlight lang="clojure">
(0 1 2 3 4)
'''критично:''' `def` не варто використовувати для локальних проміжних значень усередині логіки.<syntaxhighlight lang="clojure">
Приклад:
updated-user
Синтаксис(.toUpperCase "hello") Головна практика: Clojure часто розробляють через REPL, поступово будуючи й перевіряючи функції на живих даних. * clojure.tools.logging;
Ring описує HTTP request і response як maps. Її сила розкривається в REPL, immutable structures, композиції і JVM-екосистемі. * організації модулів;
(alter account-b + 10))
Практична роль: deps.edn став популярним сучасним способом керування залежностями й інструментами Clojure.== Висновок == `->>` передає значення як останній аргумент: <div style="background:#fff7ed; border-left:6px solid #fb923c; padding:12px; margin:12px 0;">
Immutability
`->` передає значення як перший аргумент: Виклик instance method: Критично: data-oriented design не замінює security review. Component і Integrant — бібліотеки для керування lifecycle компонентів застосунку.Clojure має кілька інструментів для відкладених або асинхронних обчислень. Common Lisp
Рекомендовано:
</div>
</div>
<syntaxhighlight lang="clojure">
* незвичний Lisp-синтаксис;
* динамічна типізація;
* менша кадрова база;
* JVM startup time;
* складність onboarding для OOP-команд;
* потреба в REPL-культурі;
* lazy sequences можуть створювати неочевидну поведінку;
* macros можуть ускладнювати код;
* stack traces можуть бути довгими через JVM;
* performance потребує розуміння JVM і boxing;
* менше “єдиного стандартного framework” для web. (LocalDate/now)
<div style="background:#e8f8f5; border-left:6px solid #16a085; padding:12px; margin:12px 0;">
Результат:
== Testing ==
'''Висновок:''' Kotlin часто виступає як практичною модернізацією Java, а Clojure — радикальнішим data-oriented і Lisp-підходом на JVM. (:require [clojure.test :refer [deftest is testing]]
{:select [:id :name]
=== Групування даних ===
У Clojure logging часто робиться через Java logging libraries або Clojure wrappers. user
</div>
(s/def ::age int?)
(defn greet [{:keys [name]}]
(reduce +))
Protocol описує набір функцій, які можуть реалізувати різні типи. ! через Практична роль: `let` користувачі можуть давати імена проміжним результатам без створення глобальних змінних. (def user <syntaxhighlight lang="clojure">
(< age 18) "minor"
(>= age 18) "adult"
<syntaxhighlight lang="clojure">
Clojure робить акцент на простих структурах даних. * Документація Ring. Приклад:
'''Практична роль:''' protocols дають polymorphism у стилі Clojure без класичної OOP-ієрархії. (let [name "Alice"
Оригінальна map не змінюється. Критерій
! Java
* команд без часу на навчання Lisp-підходу;
* проєктів із великою кількістю junior-розробників без FP-досвіду;
* Android-first розробки;
* frontend без ClojureScript-експертизи;
* проєктів, де обов’язкова сильна статична типізація;
* простих CRUD-систем, де Java/Kotlin/Go/Python простіші для команди;
* організацій, де важлива широка кадрова база. (+ 1 2)
</div>
</div>
== Типові помилки початківців ==
'''Практична роль:''' Clojure web development часто виступає як бібліотечним і data-driven, а не framework-heavy. * ClojureDocs.<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
== Maps ==
'''Практична роль:''' Malli часто використовують у сучасних Clojure-проєктах для опису й перевірки даних. Оголошення функції:
Це дає доступ до:
</div>
! '''Практична роль:''' atom дає можливість змінювати стан без класичного shared mutable object-підходу.<div style="background:#e8f8f5; border-left:6px solid #16a085; padding:12px; margin:12px 0;">
(nth numbers 0)
! '''Основна ідея:''' Clojure поєднує Lisp-підхід, функціональне програмування, незмінні структури даних і доступ до JVM-екосистеми. (defn greet [name]
</div>
== Коли варто використовувати Clojure ==
<syntaxhighlight lang="clojure">
<syntaxhighlight lang="clojure">
(alter account-a - 10)
* SQL queries;
* connection pooling;
* transactions;
* result sets as data;
* JDBC integration;
* backend services.== Див. так само ==
(when active? Lisp-підхід дає Clojure:
Vector destructuring:
<syntaxhighlight lang="clojure">
Простий приклад:
Clojure здатна бути не найкращим вибором для:
</div>
<div style="background:#ecfdf5; border-left:6px solid #10b981; padding:12px; margin:12px 0;">
Clojure не забороняє стан, але робить його явним і контрольованим.
(str "User: " (:name x))))
(->> [1 2 3 4 5]
(deliver p 42)
<syntaxhighlight lang="clojure">
(defrecord User [name age])
[:find ?name Threading macrosПриклад: Практична роль: Ring робить web-розробку в Clojure data-oriented: request і response — це звичайні maps. |- |
Платформа | JVM | JVM |
|---|---|---|---|
| Парадигма | Функціональна, data-oriented | Переважно об’єктно-орієнтована | |
| інформаційні дані | Immutable persistent data structures | Mutable objects, records, collections | |
| Синтаксис | Lisp/S-expressions | C-подібний синтаксис | |
| ERP-платформа | Clojure + Java libraries | Дуже велика Java-екосистема | |
| REPL | Центральна практика | Не основна практика |
Поширені помилки:
Protocols
</syntaxhighlight>
(let [{:keys [name age]} {:name "Alice" :age 25}]
<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
(->> [1 2 3 4 5]
{:status 200
</div>
|-
| Типізація
| Динамічна
| Статична
|-
| Парадигма
| Functional, Lisp, data-oriented
| FP + OOP, strong type system
|-
| Складність
| Простий синтаксис, сильні runtime-концепції
| Складніша type system
|-
| інформаційні дані
| Immutable maps, vectors, sets
| Case classes, ADTs, collections
|-
| JVM interop
| Сильний
| Сильний
|}
<syntaxhighlight lang="clojure">
@result
lein test
== Java interop ==
`(if (not ~condition)
Практична роль: core.async дає можливість будувати системи, де компоненти обмінюються значеннями через канали.== Lisp-походження == (+ 1 2 3)
Перевага синтаксису: Clojure має мало спеціальних правил, тому більшість коду виглядає як виклик функцій. Це означає, що її синтаксис базується на S-expressions — списках, де першим елементом зазвичай виступає як функція або оператор.(testing "addition"
Keywords можуть так само працювати як функції для отримання значення з map:
(def user
"adult"
:active true})
Component і Integrant
HoneySQL дає можливість будувати SQL-запити як Clojure data structures. (map #(* % 10)))
Скорочений синтаксис:
<syntaxhighlight lang="clojure">
Datomic орієнтована на:
Це дає:
- Програмування
- Мова програмування
- Lisp
- Common Lisp
- Scheme
- Java
- Scala
- Kotlin
- Python
- JVM
- Functional programming
- Immutable data
- REPL
- ClojureScript
- Ring
- Reitit
- Datomic
- Reagent
- Re-frame
- Backend
- Concurrency
- Налагодження коду
- Логування
- Безпека застосунків