Перейти до вмісту

Clojure

Матеріал з K2 ERP Wiki

(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>
У Clojure `nil` означає відсутність значення.
<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. Критерій

Property-based testing перевіряє не один приклад, а загальну властивість функції на багатьох згенерованих даних.

Приклад:

Приклад:

: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})

Джерела

Clojure використовує persistent data structures. * Документація Datomic.
Для цього краще `let`. backend-сервісів забезпечується через Clojure використовують; так само реалізовано data processing, фінансових систем, web applications, інтеграцій, DSL, аналітичних інструментів, JVM-застосунків, event-driven систем і проєктів, де важлива гнучкість, композиційність і контроль стану. Macros використовуються для:

(reduce + [1 2 3 4 5])

  • immutability;
  • ефективні оновлення версій;
  • безпечне розділення даних;
  • зручну історію станів;
  • менше помилок від shared mutable state;
  • гарну основу для concurrent programming.

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

  • polymorphism;
  • extension points;
  • library design;
  • behaviour contracts;
  • роботи з різними типами;
  • зменшення залежності від класів. :active true})

Тести використовуються для:

Приклад:

'(1 2 3)

Compojure застосовується для для:

</syntaxhighlight>

(str "Hello, " name))

</syntaxhighlight> (defn normalize [text] Malli — популярна бібліотека для data schemas у Clojure. (:name user)

HoneySQL

clojure.spec — інструмент для опису структури даних і перевірки відповідності.
  • списків значень;
  • аргументів функцій;
  • результатів запитів;
  • послідовностей;
  • структурованих даних;
  • координат;
  • small tuples. Clojure часто застосовується для в backend і фінансових системах, тому приватність даних важлива. (if (> age 18)

HoneySQL корисний для:

Приклад:

Увага: хороша структура namespaces дуже важлива для підтримуваності Clojure-проєкту. ! "minor")

(+ a b c))

інформаційні дані в Clojure

  • JVM backend;
  • data-oriented systems;
  • складних бізнес-доменів;
  • REPL-driven development;
  • integration services;
  • financial systems;
  • data processing;
  • DSL;
  • immutable state models;
  • ClojureScript frontend;
  • full-stack функціонального підходу;
  • систем, де важлива гнучкість даних;
  • teams із досвідом functional programming. Clojure і Common Lisp належать до Lisp-сімейства, але мають різний фокус.
    (deftest add-test
    
    </div>
    

(import java.time.LocalDate)

Практична роль: set зручний, коли важлива саме наявність значення, а не порядок.
  • великих даних;
  • нескінченних послідовностей;
  • pipeline processing;
  • відкладених обчислень;
  • економії пам’яті. (filter even?)
Практична роль: next.jdbc дає можливість працювати з SQL у Clojure, зберігаючи data-oriented підхід. !

Higher-order functions

Datomic

(Math/sqrt 16)

  • frontend apps;
  • React UI;
  • dashboards;
  • internal tools;
  • ClojureScript interfaces;
  • functional UI components.</syntaxhighlight>

(swap! [1 2 3 4 5])

  • виконувати код одразу;
  • перевіряти функції;
  • досліджувати інформаційні дані;
  • працювати з running application;
  • інтерактивно налагоджувати логіку;
  • оперативно змінювати код;
  • будувати систему поступово;
  • тестувати ідеї без повного перезапуску. Критерій

</syntaxhighlight> </syntaxhighlight>

Практична роль: property-based testing добре поєднується з Clojure, бо мова орієнтована на інформаційні дані й чисті функції.</syntaxhighlight>

  • Офіційна документація Clojure. @log-state

Загальний SEO-опис

  • передавати поведінку як аргумент;
  • комбінувати логіку;
  • опрацьовувати колекції декларативно;
  • уникати явних циклів;
  • будувати гнучкі pipelines.</syntaxhighlight>

Reagent

== Vectors ==

Практична роль: Clojure не ізольована мова — вона здатна використовувати велику JVM-екосистему й працювати поруч із Java-кодом.== JVM == Приклад literal list:

Потрібно контролювати:

age
{:name "Alice"
Практична роль: lifecycle-бібліотеки допомагають будувати Clojure-застосунки, які інтуїтивно запускати, зупиняти й перезавантажувати в REPL. Clojure і Scala обидві працюють на JVM, але мають різну філософію. * Документація Clojure CLI і deps.edn.
<syntaxhighlight lang="clojure">

 :body "Hello from Clojure"})
Spec здатна використовуватися для:

</syntaxhighlight>

Destructuring

Перевага threading macros: вони дозволяють читати послідовність перетворень зверху вниз. Водночас вона має незвичний синтаксис, динамічну типізацію, меншу кадрову базу й потребує готовності команди працювати у функціональному стилі.

</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;

  • Logback;
  • SLF4J;
  • Timbre;
  • structured logging;
  • JSON logs;
  • tracing;
  • metrics.
    <syntaxhighlight lang="clojure">
    == Refs і STM ==
    <div style="background:#fff7ed; border-left:6px solid #fb923c; padding:12px; margin:12px 0;">
     {:name "Bob" :role :user}
    
    Reagent дає можливість писати UI як ClojureScript-функції й data structures. ! '''критично:''' spec оптимізує зробити data-oriented код більш контрольованим, але не замінює повну статичну типізацію.<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
    
    </div>
    Ring застосовується для як основа для:
    <div style="background:#e8f8f5; border-left:6px solid #16a085; padding:12px; margin:12px 0;">
    == Обмеження Clojure ==
    |-
    | Платформа
    | JVM, ClojureScript, CLR-варіанти
    | Різні реалізації Common Lisp
    |-
    | інформаційні дані
    | Immutable persistent data structures
    | Більш традиційні mutable structures
    |-
    | Concurrency
    | Сучасні Clojure primitives
    | Залежить від реалізації
    |-
    | ERP-платформа
    | JVM і Clojure libraries
    | Common Lisp ecosystem
    |-
    | Стиль
    | Data-oriented functional Lisp
    | Дуже гнучкий multi-paradigm Lisp
    |}
    
     (filter odd?)
    <syntaxhighlight lang="clojure">
    

Ring описує HTTP request і response як maps. Її сила розкривається в REPL, immutable structures, композиції і JVM-екосистемі. * організації модулів;

  • підключення бібліотек;
  • уникнення конфліктів імен;
  • структури проєкту;
  • public API;
  • тестів. (+ 1 2 3)
(alter account-b + 10))
  • DSL;
  • control flow;
  • code generation;
  • test syntax;
  • web routing;
  • database query DSL;
  • зменшення boilerplate.

Практична роль: deps.edn став популярним сучасним способом керування залежностями й інструментами Clojure.== Висновок == `->>` передає значення як останній аргумент:

<div style="background:#fff7ed; border-left:6px solid #fb923c; padding:12px; margin:12px 0;">

Immutability

  • database connections;
  • web server;
  • configuration;
  • background workers;
  • message queues;
  • dependency graph;
  • start/stop lifecycle;
  • REPL-friendly development.

`->` передає значення як перший аргумент: Виклик 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.== Див. так само ==
Висновок: Common Lisp виступає як класичною потужною Lisp-системою, а Clojure — сучасним Lisp для JVM і immutable data.
(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 орієнтована на:

Це дає:

Clojure і Python