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

Clojure

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

Це означає виклик функції `+` з аргументами `1`, `2`, `3`.;</syntaxhighlight> Приклад:

Clojure має невелику кількість синтаксичних форм.; (def updated-user (assoc user :age 26))

<syntaxhighlight lang="clojure">

`promise`:

Clojure має кілька умовних форм.; * Документація Datomic.; '''Leiningen''' — класичний build tool для Clojure.; Common Lisp
<div style="background:#ecfdf5; border-left:6px solid #10b981; padding:12px; margin:12px 0;">
'''Висновок:''' Scala робить ставку на статичну типізацію й type system, а Clojure  на прості інформаційні дані, runtime-гнучкість і REPL.; `def` створює var у namespace.;== Java interop ==
Приклад створення обєкта:

Групування даних

</syntaxhighlight>

(str/lower-case (str/trim text)))
 :where [:= :active true]}

Clojure належить до родини Lisp.; Це означає, що її синтаксис базується на S-expressions — списках, де першим елементом зазвичай є собою функція або оператор.; Оригінальна map не змінюється.; '(1 2 3)
 (str name " is " age))

</div>

* frontend apps;
* React UI;
* dashboards;
* internal tools;
* ClojureScript interfaces;
* functional UI components.; '''Суть persistent structures:''' нова реліз даних створюється результативно, без повного копіювання всієї структури в типових випадках.; Clojure застосовується для:
[:find ?name
 (print-value [x]

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

Ring

 :age 25

Для функцій зазвичай використовують `defn`:

== Multimethods ==
user
== Clojure і Python ==

{| class="wikitable"
<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
(defn handler [request]

!; Malli застосовується для:

</div>

* 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.; (:name user)

</syntaxhighlight>

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

* асинхронних оновлень;
* background state transitions;
* serialized updates;
* event processing;
* незалежних stateful обєктів.;</div>

(LocalDate/now)

== Malli ==

 {:status 200

 (update :age inc))
Clojure і Common Lisp належать до Lisp-сімейства, але мають різний фокус.; '''Практична роль:''' deps.edn став популярним сучасним способом керування залежностями й інструментами Clojure.; datasource ["select * from users"])

(defmethod describe :user [x]

* web services;
* interceptors;
* API;
* long-running services;
* enterprise backend;
* data-driven request processing.; * Документація Ring.; `->>` передає значення як останній аргумент:

(def users

backend-сервісів забезпечується через Clojure використовують; додатково реалізовано data processing, фінансових систем, web applications, інтеграцій, DSL, аналітичних інструментів, JVM-застосунків, event-driven систем і проєктів, де важлива гнучкість, композиційність і контроль стану.; * Документація Clojure CLI і deps.edn.; (async/go

Macros

(str "User: " (:name x)))
  • списки `(...)`;
  • вектори `[...]`;
  • maps `{...}`;
  • sets `#{...}`;
  • symbols;
  • keywords;
  • functions;
  • special forms;
  • macros.;

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

</syntaxhighlight>

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

Clojure використовує persistent data structures.;=== Простий Ring handler ===

{:deps {org.clojure/clojure {:mvn/version "1.11.1"}}

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

Clojure і Python обидві динамічні, але мають різні ніші.;

Clojure має змогу бути не найкращим вибором для:
'''Практична роль:''' Re-frame дає структурований підхід до великих ClojureScript frontend-застосунків.; [1 2 3 4 5])

== Перша програма на Clojure ==

 42))
'''Map'''  key-value структура.; Вона добре підходить для backend-систем, інтеграцій, data processing, фінансових застосунків, DSL, ClojureScript frontend і складних доменних моделей.; Критерій
'''Clojure'''  це сучасна функціональна Lisp-мова для JVM, яка робить акцент на immutable data, простих структурах, REPL-driven development, Java interop і data-oriented design.;== State management ==
</div>

REPL або Read-Eval-Print Loop — ключовий інструмент Clojure-розробки.; (assoc :role :admin)

</syntaxhighlight>

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

Поширені підходи: Приклад:

discount-value (* subtotal discount)]

(defn greet [name]

</syntaxhighlight>

user=> (+ 2 3) Головна практика: Clojure часто розробляють через REPL, поступово будуючи й перевіряючи функції на живих даних.; Compojure — routing library для Ring.; (def user

Clojure і Scala

Atoms

  • боротися з дужками замість розуміння структури;
  • писати Clojure як Java;
  • використовувати mutable state без потреби;
  • створювати занадто багато records там, де достатньо maps;
  • надмірно використовувати macros;
  • не розуміти lazy sequences;
  • плутати `->` і `->>`;
  • зловживати nested anonymous functions;
  • створювати великі namespaces без структури;
  • не використовувати REPL;
  • не тестувати pure functions;
  • ігнорувати nil;
  • не валідувати external input.; {:name "Carol" :role :user}])

Практична роль: Reitit часто обирають для сучасних Clojure API через data-driven підхід і хорошу інтеграцію зі схемами.; * ClojureDocs.;

Практична роль: Compojure — класичний легкий спосіб описувати маршрути в Clojure web applications.;</syntaxhighlight>

Clojure має змогу використовувати Maven-залежності.; * Документація clojure.test.; (println "Hello, world!")

(def expensive

  • команд без часу на навчання Lisp-підходу;
  • проєктів із великою кількістю junior-розробників без FP-досвіду;
  • Android-first розробки;
  • frontend без ClojureScript-експертизи;
  • проєктів, де обов’язкова сильна статична типізація;
  • простих CRUD-систем, де Java/Kotlin/Go/Python простіші для команди;
  • організацій, де важлива широка кадрова база.; (fn [x] (* x x))

(async/go

(print-value [x]))

Re-frame

(jdbc/execute!;</syntaxhighlight>

Практична роль: core.async надає можливість будувати системи, де компоненти обмінюються значеннями через канали.; Це означає, що при “зміні” структури створюється нова реліз, яка результативно розділяє частину пам’яті зі старою.;

(defn greet [name] (->> [1 2 3 4 5]

(defn normalize [text]

Sequence abstraction — одна з ключових ідей Clojure.; (swap!; Практична роль: atom надає можливість змінювати стан без класичного shared mutable object-підходу.; Macros використовуються для:

Printable

Protocol описує набір функцій, які можуть реалізувати різні типи.;

(println "computing")

(def numbers [1 2 3 4 5])

(deftest add-test

* 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 функціональних застосунків.; (defmacro unless [condition & body]

(defroutes app

 (is (= 5 (core/add 2 3)))))

Приклад handler:

(def p (promise))

<div style="background:#e8f8f5; border-left:6px solid #16a085; padding:12px; margin:12px 0;">
'''Перевага JVM-екосистеми:''' Clojure має змогу підключати як Clojure-бібліотеки, так і Java-бібліотеки з Maven-світу.; * Документація Compojure.; * проміжних значень;
* читабельності;
* локального scope;
* уникнення дублювання;
* розбиття складної логіки.; * frontend applications;
* React-based UI;
* single-page applications;
* Reagent;
* Re-frame;
* full-stack Clojure/ClojureScript systems;
* interactive web tools;
* dashboards;
* internal interfaces.; Scala
(map #(* % 10))

Приклад:

Keywords

(group-by :role users) (-> {:name "Alice" :age 25}

; :active true}) ; Результат:

lein run

  • atoms;
  • refs;
  • agents;
  • vars;
  • delays;
  • promises;
  • futures.;
    === Обробка списку ===
    
    * web applications;
    * middleware;
    * HTTP handlers;
    * REST API;
    * routing libraries;
    * server integration.;<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
    
    '''Увага:''' agents підходять не для будь-якої concurrency-задачі.; (map inc [1 2 3])
    (str "Hello, " "world")
    
    == Коли Clojure має змогу бути невдалим вибором ==
    
    <div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
    </div>
    Основні інструменти для state:
    

(+ 1 2 3) Приклад: </syntaxhighlight>

(delay
Clojure робить акцент на простих структурах даних.;
@counter
'''Висновок:''' Python універсальніший і популярніший, а Clojure сильніша там, де потрібні JVM, immutable data й REPL-driven functional design.;

(def account-a (ref 100))

Leiningen

<div style="background:#eef2ff; border-left:6px solid #4f46e5; padding:12px; margin:12px 0;">
`assoc` створює нову map, а не змінює стару.; '''Головне правило:''' хороший Clojure-код має бути простим, data-oriented, функціональним і зрозумілим у REPL.; '''Перевага синтаксису:''' Clojure має мало спеціальних правил, з цієї причини більшість коду виглядає як виклик функцій.; roles :admin)

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

* immutability;
* ефективні актуалізація;
* безпечне розділення даних;
* зручну історію станів;
* менше помилок від shared mutable state;
* гарну основу для concurrent programming.; Водночас вона має незвичний синтаксис, динамічну типізацію, меншу кадрову базу й потребує готовності команди працювати у функціональному стилі.;<syntaxhighlight lang="clojure">
<syntaxhighlight lang="clojure">
 (:require [clojure.test :refer [deftest is testing]]

Keywords можуть додатково працювати як функції для отримання значення з map:

Приклади властивостей:

  • доступ до Java-бібліотек;
  • mature runtime;
  • garbage collection;
  • tooling;
  • monitoring;
  • performance capabilities;
  • deployment у Java-екосистемі;
  • інтеграцію з enterprise-системами;
  • доступ до Maven-репозиторіїв;
  • cross-platform виконання.; Валідація, доступи, secrets і залежності мають перевірятися окремо.; Критерій
  • pure functions;
  • data transformations;
  • API handlers;
  • business rules;
  • regression checks;
  • integration tests;
  • REPL-driven verification.;
    <div style="background:#ecfdf5; border-left:6px solid #10b981; padding:12px; margin:12px 0;">
    
    * організації модулів;
    * підключення бібліотек;
    * уникнення конфліктів імен;
    * структури проєкту;
    * public API;
    * тестів.;<syntaxhighlight lang="clojure">
    Рекомендовано:
    </div>
    
    Результат:
    

(if (> age 18)

Clojure macros можливі з цієї причини, що код має структуру даних.;

Reitit

Lists

</syntaxhighlight>

Property-based testing

Висновок

(->> [1 2 3 4 5]

  • унікальних значень;
  • перевірки належності;
  • ролей;
  • tags;
  • множинних операцій;
  • фільтрації.; Приклад:

істотно: logging у Clojure-системах має бути структурованим і не повинен розкривати secrets або персональні інформаційні дані.;</syntaxhighlight> Перевага: Clojure надає можливість писати компактний, композиційний і гнучкий код, зберігаючи доступ до Java-бібліотек і JVM-інфраструктури.; Виклик instance method: </syntaxhighlight>

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

Головна перевага: Clojure надає можливість моделювати систему як перетворення даних, а не як мережу mutable objects.;== REPL ==

Практична роль: property-based testing добре поєднується з Clojure, бо мова орієнтована на інформаційні дані й чисті функції.;
* писати маленькі 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 обережно.; @log-state
(require '[compojure.core :refer [defroutes GET]])
Приклад:

'''Namespace''' організовує код і контролює імена.; (defn handler [request]
`deps.edn` описує:
Refs корисні, коли потрібно координовано змінити кілька значень у транзакції.; REPL надає можливість:

Приклад ідеї Datalog-запиту:

!; Основні структури:
(assoc user :age 26)

<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
<syntaxhighlight lang="clojure">
Clojure функціонує на '''Java Virtual Machine'''.; Clojure

</div>

<div style="background:#fef2f2; border-left:6px solid #ef4444; padding:12px; margin:12px 0;">
'''Практична роль:''' destructuring робить роботу з maps і vectors компактною й читабельною.; Критерій

HoneySQL корисний для: застосовується для: </syntaxhighlight>

:from [:users]
:body "Hello from Ring"})

Приклад Java interop: Виклик: Re-frame базується на:

Практична роль: ClojureScript надає можливість використовувати Clojure-підхід у браузері й будувати frontend у функціональному стилі.;
* numbers;
* strings;
* booleans;
* nil;
* keywords;
* symbols;
* lists;
* vectors;
* maps;
* sets.; Багато колекцій можна обробляти однаково як послідовності:

<syntaxhighlight lang="clojure">
</div>
'''Практична роль:''' Datomic добре поєднується з Clojure-філософією immutable data і data-oriented design.; lein test
(defprotocol Printable
</div>

!; Clojure має кілька інструментів для відкладених або асинхронних обчислень.; '''Практична роль:''' Reagent робить React-розробку ближчою до Clojure-підходу: UI як інформаційні дані й функції.;</div>
</div>
 (- subtotal discount-value)))

Clojure має вбудовану бібліотеку `clojure.test`.; '''Reitit''' — сучасна routing library для Clojure і ClojureScript.; `if`:

{:select [:id :name]
'''Практична роль:''' Malli часто використовують у сучасних Clojure-проєктах для опису й перевірки даних.; * Документація ClojureScript, Reagent і Re-frame.; (->> [1 2 3 4 5]

== Maps ==

 (let [subtotal (* price quantity)
Приклад:
'''Основна ідея:''' Clojure поєднує Lisp-підхід, функціональне програмування, незмінні структури даних і доступ до JVM-екосистеми.;

</syntaxhighlight>

5

Приклад:

Re-frame — framework для ClojureScript frontend-застосунків поверх Reagent.;== Безпека Clojure-застосунків ==

HoneySQL

Приклад: Головна структура Clojure: maps часто є собою основою доменних даних, API payloads, конфігурацій і проміжних результатів.; Clojure

Практична роль: vectors є собою однією з найчастіших структур Clojure для впорядкованих даних.;</syntaxhighlight> (defmethod describe :order [x] Приклад:

* DSL;
* control flow;
* code generation;
* test syntax;
* web routing;
* database query DSL;
* зменшення boilerplate.;</div>
</div>
'''істотно:''' круглі дужки в Clojure зазвичай означають не “групування”, а виклик функції або special form.; Потрібно контролювати:

<syntaxhighlight lang="clojure">
<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
== Vars і def ==
(defn total-price [{:keys [price quantity discount]}]
|-
| Платформа
| JVM, ClojureScript, CLR-варіанти
| Різні реалізації Common Lisp
|-
| інформаційні дані
| Immutable persistent data structures
| Більш традиційні mutable structures
|-
| Concurrency
| Сучасні Clojure primitives
| Залежить від реалізації
|-
| програмний пакет
| JVM і Clojure libraries
| Common Lisp ecosystem
|-
| Стиль
| Data-oriented functional Lisp
| Дуже гнучкий multi-paradigm Lisp
|}

'''Практична роль:''' lifecycle-бібліотеки допомагають будувати Clojure-застосунки, які комфортно запускати, зупиняти й перезавантажувати в REPL.;== Загальний характеристика ==

== Pedestal ==
<syntaxhighlight lang="clojure">
<div style="background:#ecfdf5; border-left:6px solid #10b981; padding:12px; margin:12px 0;">
 "minor")
 {:name "Alice"
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">

 (testing "addition"

== Clojure і Java ==
'''ClojureScript'''  це варіант Clojure, який компілюється в JavaScript.; Потрібно розуміти, коли потрібен agent, atom, core.async або інший підхід.; * великих даних;
* нескінченних послідовностей;
* pipeline processing;
* відкладених обчислень;
* економії пам’яті.; * Документація Leiningen.;<syntaxhighlight lang="clojure">
Основні елементи:

Clojure-екосистема підтримує роботу property-based testing, зокрема через test.check.; {:name "Alice"

<div style="background:#e8f8f5; border-left:6px solid #16a085; padding:12px; margin:12px 0;">
'''Практична порада:''' Clojure варто обирати, коли команда готова працювати з функціональним data-oriented підходом і хоче використовувати JVM.; (do ~@body)))
'''Критично:''' data-oriented design не замінює security review.; Її сила розкривається в REPL, immutable structures, композиції і JVM-екосистемі.; це сучасна функціональна мова програмування з родини Lisp, яка функціонує переважно на '''JVM''' і орієнтована на immutable data, простоту моделей даних, REPL-driven development, concurrency і практичну розробку складних систем виступає ключовою рисою '''Clojure'''.;== ClojureScript ==
(s/def ::user (s/keys :req [::name ::age]))

 (str "User: " (:name x))))
 :age 25

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

(println (greet "Alice"))
'''Malli'''  популярна бібліотека для data schemas у Clojure.; * Документація core.async.; (filter odd?)

(if [] "truthy" "falsey")

(let [name "Alice" Приклад:

переважні аспекти Clojure

</syntaxhighlight>

Agents корисні для:

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

Виклик static method:

Практична роль: set зручний, коли важлива саме наявність значення, а не порядок.; (str "Hello, " name))

(def user {:name "Alice" :age 25})

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

 (-> user

'''Практична роль:''' Clojure добре підходить для тестування, бо багато логіки можна оформити як чисті функції над даними.; '''Atom''' — механізм для синхронної, незалежної зміни стану.; Приклад ідеї:

(def user

clojure.spec — інструмент для опису структури даних і перевірки відповідності.;
</div>
'''істотно:''' Clojure має змогу дати велику продуктивність сильній команді, але потребує культурної згоди щодо стилю, REPL і функціонального мислення.; {| class="wikitable"
</div>

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

 {:name "Alice"
</div>

Agents

Див.; додатково

{:deps {cheshire/cheshire {:mvn/version "5.12.0"}}}

Compojure

(contains?;

Set — колекція унікальних значень.; counter inc)

(require '[clojure.core.async :as async])

Protocols використовуються для:
 (reduce +))

Web development

</syntaxhighlight>

  • `defn` створює функцію;
  • `str` об’єднує рядки;
  • `println` виводить результат;
  • аргументи функції записуються у векторі `[name]`.;== Lisp-походження ==

Clojure розроблена як практична Lisp-мова для сучасної розробки.; (map #(* % 10)))

(ns my-app.core

</syntaxhighlight>

Джерела

Sets використовуються для: Spec має змогу використовуватися для:

Приклади:

  • простих web routes;
  • REST API;
  • Ring applications;
  • internal tools;
  • невеликих backend-сервісів.;== Persistent data structures ==
[{:name "Alice" :role :admin}

Функції

(when active?; Python

Функції вищого порядку дозволяють:

Namespaces

Приклад:

</syntaxhighlight>

Namespaces використовуються для: (cond

Reagent

:where

Приклад:

</syntaxhighlight>

Pedestal — web framework і набір інструментів для Clojure services.;

Критично: macros дуже потужні, але їх варто писати лише тоді, коли звичайних функцій недостатньо.; Помилка: сприймати Clojure як Java з дужками.; Небезпека: Clojure надає можливість писати дуже компактний код, але надмірна компактність має змогу зробити логіку важкою для читання.; Приклад ідеї:

:headers {"Content-Type" "text/plain"}

Головна ідея даних: Clojure заохочує описувати домен через прості immutable data structures, а не через складні mutable objects.; Критерій `let` корисний для:

Maven dependencies

; Окремо варто відзначити хто хоче будувати системи навколо даних і функцій, а не навколо mutable object-ієрархій.;
:active true})

@expensive

(require '[next.jdbc :as jdbc]) </syntaxhighlight>

updated-user

(async/>!;== інформаційні дані в Clojure ==

Clojure дає компактність, гнучкість, потужні macros, persistent data structures і доступ до JVM-екосистеми.; У Clojure інформаційні дані за замовчуванням immutable.; Vector destructuring: </syntaxhighlight> (add 2 3)

; (str name " is " age))

(nth numbers 0) (def user {:name "Alice" :age 25})

</syntaxhighlight>

  • polymorphism;
  • extension points;
  • library design;
  • behaviour contracts;
  • роботи з різними типами;
  • зменшення залежності від класів.; !;
  • database connections;
  • web server;
  • configuration;
  • background workers;
  • message queues;
  • dependency graph;
  • start/stop lifecycle;
  • REPL-friendly development.; Vector — впорядкована indexed collection.; Вектори часто використовуються для:

{{SEO


Практична роль: protocols дають polymorphism у стилі Clojure без класичної OOP-ієрархії.; `future`:

Clojure і Common Lisp

(assoc :active true)
У цьому прикладі:
== Приватність даних ==

== Приклади задач на Clojure ==
<div style="background:#fdecea; border-left:6px solid #e74c3c; padding:12px; margin:12px 0;">
Reitit підтримує роботу:

Приклад:

(dosync
#(* % %)
'''Datomic'''  база даних, тісно повязана з Clojure-екосистемою.; '''Головна думка:''' Clojure — це мова для тих.; @p

(defmulti describe :type)
Clojure-застосунки мають звичайні security-ризики JVM і web-систем.; (defrecord User [name]
== Sets ==
Анонімна функція:

'''Висновок:''' Kotlin часто є собою практичною модернізацією Java, а Clojure  радикальнішим data-oriented і Lisp-підходом на JVM.; Ефективний Clojure-код потребує іншого мислення: інформаційні дані, функції, immutability і REPL.; Вона каже: стан має бути контрольованим, явним і відокремленим від чистих функцій.; (send log-state conj "event")
== Коли варто використовувати Clojure ==

</div>

 :headers {"Content-Type" "text/plain"}
(def result
Lisp-підхід дає Clojure:
<syntaxhighlight lang="clojure">
 `(if (not ~condition)
(0 1 2 3 4)

'''Суть прикладу:''' Clojure-код складається з виразів, які обчислюються й повертають значення.;<div style="background:#ecfdf5; border-left:6px solid #10b981; padding:12px; margin:12px 0;">
<syntaxhighlight lang="clojure">

`when`:
'''Увага:''' у Clojure порожня колекція не є собою false.; * Матеріали щодо functional programming, immutable data, REPL-driven development і JVM interop.; Для цього краще `let`.; * Clojure libraries;
* Java libraries;
* Maven Central;
* private Maven repositories;
* enterprise artifacts;
* JVM tooling.; Clojure

<syntaxhighlight lang="clojure">

 (future

 (reduce +))

* сортування зберігає кількість елементів;
* encode/decode повертає початкове значення;
* сума не залежить від порядку елементів;
* функція не падає на валідних input.; * Clojure Reference.; [:div "Hello from Reagent"])
== next.jdbc ==
 (< age 18) "minor"
 (>= age 18) "adult"

== Protocols ==
core.async застосовується для:
<syntaxhighlight lang="clojure">

Ring описує HTTP request і response як maps.;== Threading macros ==
(import java.time.LocalDate)

 :active true})

Приклад dependency:

У функції:

updated-user
(def updated-user
 :body "Hello from Clojure"})

Обмеження Clojure

</syntaxhighlight> Приклад:

Синтаксис

Приклад:

</syntaxhighlight>

Висновок: Common Lisp є собою класичною потужною Lisp-системою, а Clojure — сучасним Lisp для JVM і immutable data.; ch "hello")) </syntaxhighlight> Clojure часто порівнюють із Java.; Clojure застосовується для web development, хоча зазвичай не через один монолітний framework, а через набір бібліотек.; Приклад:

{:name "Bob" :role :user}

Clojure активно використовує функції вищого порядку.; Практична роль: STM надає можливість безпечніше координувати кілька пов’язаних змін стану.; |-

Платформа JVM JVM
Парадигма Функціональна, data-oriented Переважно об’єктно-орієнтована
інформаційні дані Immutable persistent data structures Mutable objects, records, collections
Синтаксис Lisp/S-expressions C-подібний синтаксис
програмний пакет Clojure + Java libraries Дуже велика Java-екосистема
REPL Центральна практика Не основна практика

Clojure підтримує роботу lazy sequences — послідовності, які обчислюються поступово.; (update user :age inc)

(take 5 (range))

Перевага threading macros: вони дозволяють читати послідовність перетворень зверху вниз.;
</div>

* створення проєктів;
* запуску REPL;
* керування dependencies;
* запуску тестів;
* packaging;
* deployment;
* створення uberjar.; '''Практична роль:''' Leiningen довго був стандартним інструментом для Clojure-проєктів і досі часто зустрічається в existing codebase.;<syntaxhighlight lang="clojure">

'''Практична роль:''' next.jdbc надає можливість працювати з SQL у Clojure, зберігаючи data-oriented підхід.;<syntaxhighlight lang="clojure">

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

"Unknown")

У Clojure logging часто робиться через Java logging libraries або Clojure wrappers.; (defn greet [{:keys [name]}]

Clojure має сильну взаємодію з Java.;
<syntaxhighlight lang="clojure">

<syntaxhighlight lang="clojure">

<syntaxhighlight lang="clojure">

* SQL queries;
* connection pooling;
* transactions;
* result sets as data;
* JDBC integration;
* backend services.;

(defn add [a b]

Logging

Практична роль: Clojure web development часто є собою бібліотечним і data-driven, а не framework-heavy.; Agent застосовується для асинхронної зміни стану.; * персональні інформаційні дані;

  • фінансові інформаційні дані;
  • logs;
  • event streams;
  • database records;
  • API payloads;
  • secrets;
  • tokens;
  • REPL-доступ до production;
  • test fixtures;
  • data dumps;
  • monitoring output.; Без quote Clojure сприймає список як виклик функції:

</syntaxhighlight>

age 25]

</syntaxhighlight>

Immutability

Testing

Практична порада: SQL як інформаційні дані має змогу бути зручним, але складні запити все одно потрібно читати, тестувати й оптимізувати як SQL.; !;

Тематичні мітки

|-
| Платформа
| JVM
| JVM, Android, multiplatform
|-
| Типізація
| Динамічна
| Статична
|-
| Стиль
| Lisp, functional, data-oriented
| Pragmatic OOP/FP
|-
| Android
| Не основна ніша
| Сильна ніша
|-
| Enterprise adoption
| Нішевіша
| Ширша для Java-команд
|}

</div>
<div style="background:#e8f8f5; border-left:6px solid #16a085; padding:12px; margin:12px 0;">
== Хороші практики Clojure ==

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

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

<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
Clojure часто застосовується в backend і фінансових системах, з цієї причини приватність даних важлива.; Критерій

* 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.; (Math/sqrt 16)

(def user (->User "Alice" 25))

</div>

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

У Clojure `nil` означає відсутність значення.;== If, when і cond ==

'''Практична роль:''' `if` підходить для двох варіантів, `when`  для дії за умовою, `cond`  для кількох умов.; Можливі складнощі:
завдяки наявності '''Практична роль:''' `let` користувачі можуть давати імена проміжним результатам без створення глобальних змінних.; '''Multimethod''' надає можливість обирати реалізацію функції за результатом dispatch-функції.; Основні переважні аспекти Clojure:
Clojure має threading macros для читабельних pipelines.; :else "unknown")

<syntaxhighlight lang="clojure">

<syntaxhighlight lang="clojure">

<syntaxhighlight lang="text">

Ring застосовується як основа для: (:name user) (def account-b (ref 50))

:age 25

Перевага Java interop: Clojure має змогу використовувати готові Java SDK, frameworks і libraries без окремого bridge-шару.; Це істотно для умов і перевірок.; істотно: Clojure не каже “стану не існує”.; (def user

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

(s/def ::age int?)

актуалізація map:

  • 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.; * single app-db;
  • events;
  • subscriptions;
  • effects;
  • coeffects;
  • pure functions;
  • reactive data flow.; !;
    (defmethod describe :default [x]
    
    Приклад функції:
     (+ a b))
    
    </div>
    
    '''Підказка:''' у Clojure-прикладах істотно дивитися на форму даних, чистоту функцій, immutability і читабельність pipelines.;</div>
    '''істотно:''' spec сприяє зробити data-oriented код більш контрольованим, але не замінює повну статичну типізацію.; '''Практична роль:''' records корисні там, де простих maps недостатньо й потрібен окремий тип.; [my-app.core :as core]))
    
    (if true "yes" "no")
    

(deliver p 42) (reduce + [1 2 3 4 5]) Destructuring надає можливість комфортно діставати значення зі структур.; Refs використовуються з Software Transactional Memory або STM.; (defrecord User [name age])

  • локального mutable state;
  • counters;
  • caches;
  • runtime configuration;
  • shared state з atomic updates;
  • простих stateful компонентів.; Kotlin
:paths ["src" "resources"]}

Nil і booleans

  • lists;
  • vectors;
  • maps;
  • sets;
  • lazy sequences;
  • ranges;
  • file lines;
  • generated data.;
    * `false`;
    * `nil`.; Скорочений синтаксис:
    </div>
    
    (.toUpperCase "hello")
    
    * списків значень;
    * аргументів функцій;
    * результатів запитів;
    * послідовностей;
    * структурованих даних;
    * координат;
    * small tuples.; Приклад:
    == Sequences ==
    Вони допомагають організувати:
    

Простий приклад:

(println (async/<! ch)))

</syntaxhighlight>

Component і Integrant

(filter even?;
(str "Hello, " name))

Висновок: Java краще знайома масовим enterprise-командам, а Clojure дає компактність, immutable data й REPL-driven development на JVM.; Правило: REPL — потужний інструмент, але доступ до production REPL або live data має бути суворо контрольований.; Leiningen застосовується для:

|-
| Основна платформа
| JVM
| CPython та інші runtime
|-
| Стиль
| Functional, Lisp, immutable data
| Multi-paradigm, scripting, data science
|-
| програмний пакет
| JVM + Clojure libraries
| Дуже широка, особливо AI/Data Science
|-
| REPL
| Центральний workflow
| є собою, але менш центральний для production
|-
| Новачкам
| Синтаксис має змогу бути незвичним
| Зазвичай простіший старт
|}

 (+ a b c))
Compojure застосовується для:
(get user :age)

'''Ring'''  базова web abstraction у Clojure.; (println "Active"))
<div style="background:#e8f8f5; border-left:6px solid #16a085; padding:12px; margin:12px 0;">

`delay`:

<syntaxhighlight lang="clojure">

'''Keyword'''  це іменоване значення, яке часто застосовують, коли потрібно як ключ у map.;<syntaxhighlight lang="clojure">
== Refs і STM ==

</div>

</div>
Приклад ідеї:

(def ch (async/chan))

* typed domain data;
* protocol implementations;
* Java interop;
* performance-sensitive structures;
* структур, яким потрібна ідентичність типу.; * data-driven routes;
* coercion;
* Swagger/OpenAPI;
* middleware;
* frontend і backend routing;
* nested routes;
* performance-oriented routing.; '''Увага:''' хороша структура namespaces дуже важлива для підтримуваності Clojure-проєкту.; lein new app my-app
'''Reagent'''  ClojureScript wrapper для React.; (require '[clojure.spec.alpha :as s])
<syntaxhighlight lang="clojure">

 (alter account-b + 10))
<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
(let [{:keys [name age]} {:name "Alice" :age 25}]

(java.util.Date.)

* Офіційна документація Clojure.; Поширені помилки:
'''Практична роль:''' Pedestal підходить для складніших backend-сервісів, де потрібен interceptor-based pipeline.; '''HoneySQL''' надає можливість будувати SQL-запити як Clojure data structures.; '''Record''' створює іменований тип, схожий на map, але з додатковими можливостями.; Це дає:

Lazy sequences корисні для:

* dependencies;
* aliases;
* paths;
* tools;
* test конфігурації;
* REPL startup;
* build tasks.;== Futures, delays і promises ==

<syntaxhighlight lang="clojure">

(let [[a b c] [1 2 3]]

  • immutable facts;
  • time-aware database;
  • Datalog queries;
  • historical data;
  • auditability;
  • data as values;
  • entity-attribute-value model.; Приклад:

(+ 1 2 3) (def app-name "My App")

(alter account-a - 10)

Приклад: Це дає доступ до:

Records

(str "Hello, " name))

Clojure добре підходить для:

List у Clojure записується в круглих дужках.;

Приклад:

core.async

істотно: `def` не варто використовувати для локальних проміжних значень усередині логіки.; !; Clojure і Scala обидві працюють на JVM, але мають різну філософію.; Приклад: завдяки наявності JVM Clojure отримує:

@result

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

== Let ==

* clojure.tools.logging;
* Logback;
* SLF4J;
* Timbre;
* structured logging;
* JSON logs;
* tracing;
* metrics.; Clojure

'''Практична роль:''' multimethods дають гнучкий polymorphism, який не привязаний лише до класу обєкта.; (+ 1 2)
(def counter (atom 0))
=== Функція для бізнес-логіки ===

</div>

'''Практична роль:''' sequence abstraction надає можливість писати універсальний код для різних типів колекцій.;</div>

<syntaxhighlight lang="clojure">

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

</div>
<div style="background:#eef2ff; border-left:6px solid #4f46e5; padding:12px; margin:12px 0;">
Приклад:
== JVM ==
== Типові помилки початківців ==

:name

'''Практична роль:''' ці інструменти дають прості моделі для async, lazy і coordinated computation.; * передавати поведінку як аргумент;
* комбінувати логіку;
* обробляти колекції декларативно;
* уникати явних циклів;
* будувати гнучкі pipelines.; `->` передає значення як перший аргумент:

Spec

(:name user)

  • простий і регулярний синтаксис;
  • код як інформаційні дані;
  • macros;
  • зручне метапрограмування;
  • гнучкі DSL;
  • REPL-driven workflow;
  • компактні вирази.;
Clojure має обмеження.;</div>
Усе інше вважається truthy, включно з `0`, порожнім рядком і порожньою колекцією.;

</syntaxhighlight>

</syntaxhighlight>

deps.edn і Clojure CLI

  • Ring;
  • Reitit або Compojure;
  • Jetty або http-kit;
  • next.jdbc;
  • HoneySQL;
  • Integrant або Component;
  • Malli або spec;
  • Timbre або tools.logging;
  • PostgreSQL;
  • Kafka або інші message systems.;
  • validation;
  • data contracts;
  • генерації тестових даних;
  • documentation;
  • runtime checks;
  • API boundaries.;== Destructuring ==

Практична роль: keywords є собою основним способом іменування полів у Clojure-даних.; `cond`:

</syntaxhighlight>

False-like значення:

Результат буде `"truthy"`.;=== актуалізація map ===

Приклад literal list:

Higher-order functions

`let` створює локальні bindings.;
</div>
<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">

Приклад ідеї:

!;

Сучасний Clojure часто використовує Clojure CLI і файл `deps.edn`.; Java істотно: lazy evaluation має змогу бути дуже корисною, але іноді створює неочевидний час виконання або утримання ресурсів.; * composable SQL;

  • dynamic queries;
  • query generation;
  • data-driven database access;
  • зменшення string concatenation у SQL.;
  • message passing;
  • pipelines;
  • async workflows;
  • coordination;
  • event processing;
  • CSP-style concurrency.; (s/def ::name string?)
:user/status
Clojure не забороняє стан, але робить його явним і контрольованим.; Приклад:
 {:status 200
'''Практична роль:''' `map`, `filter`, `reduce` і подібні функції є собою щоденними інструментами Clojure-розробника.; Приклад:
'''Практична роль:''' Ring робить web-розробку в Clojure data-oriented: request і response  це звичайні maps.; '''Component''' і '''Integrant''' — бібліотеки для керування lifecycle компонентів застосунку.;<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
(dissoc user :active)
{| class="wikitable"

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

Функції є собою основою Clojure.; Clojure

Приклад простого macro:

* validation;
* schema definitions;
* coercion;
* API validation;
* documentation;
* data-driven specs;
* frontend і backend shared schemas.; (ns my-app.core-test
(def roles #{:admin :user :manager})
(filter even?)
Macro у Clojure надає можливість перетворювати код до виконання.;
Приклад:
<syntaxhighlight lang="clojure">

 (filter even?)

'''core.async'''  бібліотека для асинхронного програмування через channels.; * Документація Reitit.; Вона не робить акцент на класичній об’єктній моделі, а пропонує будувати програми через функції, immutable data structures, namespaces, protocols, multimethods і macros.;
(GET "/" [] "Hello"))

(defn hello []

істотно: синтаксис Clojure має змогу виглядати незвично через дужки, але його регулярність є собою однією з причин сили мови.; Map destructuring: (def log-state (agent []))

(+ 40 2)))
 (map #(* % 10))

Datomic орієнтована на:
 (update :age inc)))
Оголошення функції:
!; (:require [clojure.string :as str]))
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
:age
|-
| Типізація
| Динамічна
| Статична
|-
| Парадигма
| 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">
Типовий backend stack має змогу включати:
 (str "Order: " (:id x)))

<syntaxhighlight lang="clojure">

'''next.jdbc'''  сучасна бібліотека для роботи з SQL-базами в Clojure.;<syntaxhighlight lang="clojure">
== Datomic ==
== Clojure і Kotlin ==

 [?e :user/name ?name]]

"Alice"

<syntaxhighlight lang="clojure">

!;<syntaxhighlight lang="clojure">

Головна перевага immutability: інформаційні дані не змінюються неочікувано, з цієї причини простіше думати про стан, concurrency і тестування.; Суть Clojure-коду: програми будуються як композиція функцій, які приймають інформаційні дані й повертають нові інформаційні дані.;</syntaxhighlight>

;

Reagent надає можливість писати UI як ClojureScript-функції й data structures.;<syntaxhighlight lang="clojure">

cd my-app

  • незвичний Lisp-синтаксис;
  • динамічна типізація;
  • менша кадрова база;
  • JVM startup time;
  • складність onboarding для OOP-команд;
  • потреба в REPL-культурі;
  • lazy sequences можуть створювати неочевидну поведінку;
  • macros можуть ускладнювати код;
  • stack traces можуть бути довгими через JVM;
  • performance потребує розуміння JVM і boxing;
  • менше “єдиного стандартного framework” для web.;

Lazy sequences