Skip to content
Published on

モダン Clojure 2026 完全ガイド — Clojure 1.12 · Babashka · ClojureScript · shadow-cljs · Datomic · XTDB · re-frame 徹底解剖

Authors

プロローグ — なぜ2026年に Clojure か

2026年5月、誰かが「いまどき Lisp を使う人がいるのか?」と問えば、答えは明確だ。いる、それも非常に多く。ブラジルの Nubank は1億1,000万人の顧客を抱える世界最大のデジタル銀行で、そのバックエンドはほぼすべてが Clojure で書かれている。マイクロサービスは5,000を超え、毎日数十億件のトランザクションを処理する。CircleCI は CI/CD パイプラインのコアを、Apple は一部内部ツールを、Cisco はネットワーク解析プラットフォームを、Walmart Labs は価格エンジンを Clojure で動かしている。

Clojure は2007年に Rich Hickey が発表して以来、20年近く同じ哲学を保ってきた。不変(immutable)優先・関数型・動的型付け・JVM ホスト・同時実行性をファーストクラス市民として。しかし2020年代に入ってから、Clojure のエコシステムは静かに進化した。Leiningen 一本の時代を経て、deps.edntools.deps が標準になり、ClojureScript は shadow-cljs を通じて npm エコシステム全体を取り込んだ。Babashka は GraalVM ネイティブイメージにコンパイルされ、起動速度は約20ms — Python より速い。シェルスクリプト市場で Bash と Python を同時に脅かしている。

2026年5月、Clojure 1.12 が安定化し、qualified method invocation などの Java 相互運用性改善が入った。partialloop もより賢くなった。ClojureScript 側では shadow-cljs 2.x が React 18・Vite 6・esbuild 統合を磨き上げ、re-frame 1.4 はエフェクト・イベントモデルをより洗練させた。Datomic は Pro ライセンスが事実上無償になり(Cloud は有償継続)、XTDB 2.0 は bitemporal に SQL-first を加えて PostgreSQL ユーザーにもアクセス可能になった。

そして決定的に、LLM 時代が Clojure に意外な追い風をもたらした。REPL 駆動開発は本質的に「式を一つずつ評価して結果を見る」の繰り返しだ。LLM がコードを生成し、人間が一段階ずつ検証するワークフローと完璧に噛み合う。Cursive・Calva・CIDER などのエディタは LLM 統合を強化し、REPL で LLM 応答を直接評価するパターンが定着した。

この記事は Clojure 2026 の全体像 を一本にまとめる。言語そのもの → ビルド/デプロイ → バックエンドスタック → フロントエンド → データベース → テスト → エディタ/REPL → 実運用。Nubank がどう5,000マイクロサービスを動かしているか、韓国・日本のコミュニティがどこまで来たか、そして2026年に新規参入する人がどのスタックから始めればよいかまで踏み込む。

Clojure は「使う人が少ない言語」ではない。「見えないところで重いトラフィックを受ける言語」 だ。見えているブラウザ JavaScript バックエンドが1%の市場なら、見えない1%のバックエンドが Clojure だ。

価格・バージョン数値は変動が速い。本記事のすべての数字は 2026年5月時点 であり、構造的差分に集中する。半年後にマイナーバージョンが変わっても、意思決定フレームは有効であるべきだ。


第1章 · Clojure 1.12 — 何が変わり、なぜ重要か

Clojure 1.12 は2024年9月に初リリースされ、2026年5月時点では 1.12.x パッチが安定化して事実上の標準となった。中核となる変更を3つ見る。

Qualified method invocation Java 相互運用性で最大の変更だ。従来は (.method obj arg) 形でしか呼び出せず、メソッドを関数として扱うには #(.method % arg) のようなラムダラッパーが必要だった。1.12 からはメソッドを 値として 扱える。

;; 以前 (1.11 以下)
(map #(.toUpperCase %) ["foo" "bar" "baz"])
;; => ("FOO" "BAR" "BAZ")

;; 1.12 — qualified method invocation
(map String/.toUpperCase ["foo" "bar" "baz"])
;; => ("FOO" "BAR" "BAZ")

;; 静的メソッド
(map Math/abs [-1 -2 3])
;; => (1 2 3)

;; コンストラクタも同様
(map StringBuilder/new ["hello" "world"])

String/.toUpperCase のように Class/.method 形がインスタンスメソッド、Class/method が静的メソッドまたはコンストラクタだ。Java ラムダに似た感触だが、Clojure のセマンティクスを保つ。

partial のインライン最適化 (partial f x) は新しい関数を生成して返す。1.12 からはコンパイラがインライン可能な場合にラムダと同等の性能を出す。ホットパスで partial を自由に使えるようになった。

loop の型ヒント保持 loop/recur サイクルで型ヒントが消えてしまう問題が修正された。数値計算コードでボクシングが減り、5〜15% の性能改善が報告されている。

その他: clojure.core/iteration — lazy seq の一般化。update-vals, update-keys — マップ変換ヘルパー。add-tap — デバッグフックの標準化。random-uuid — シンプルな UUID 生成器。

Clojure 1.12 は「革命」ではなく、「手工具がよく研がれた」という感触のリリースだ。しかし Java 相互運用性が滑らかになったのは大きい。Java ライブラリを気負いなく呼び出せるようになった。


第2章 · tools.deps と deps.edn — Leiningen 以後のビルド

古くからの Clojure ユーザーには project.clj(Leiningen)は馴染み深い。しかし2026年の新規プロジェクトの約70%は deps.edntools.deps を使う。違いを見る。

deps.edn 基本構造

;; deps.edn
{:paths ["src" "resources"]
 :deps {org.clojure/clojure {:mvn/version "1.12.0"}
        ring/ring-core      {:mvn/version "1.11.0"}
        metosin/reitit      {:mvn/version "0.7.0"}}
 :aliases
 {:dev {:extra-paths ["dev" "test"]
        :extra-deps {nrepl/nrepl {:mvn/version "1.3.0"}
                     cider/cider-nrepl {:mvn/version "0.47.0"}}}
  :test {:extra-paths ["test"]
         :extra-deps {lambdaisland/kaocha {:mvn/version "1.91.0"}}
         :main-opts ["-m" "kaocha.runner"]}}}

clj -X:dev のようなエイリアス呼び出しで多様な実行モードを定義する。Maven 座標がそのまま使え、Git 座標もファーストクラスサポートだ。

;; Git から直接依存
{:deps {io.github.somelibrary/lib
        {:git/url "https://github.com/somelibrary/lib.git"
         :git/sha "a1b2c3d4..."}}}

これがなぜ重要か。Maven に上がっていないライブラリ、フォークしたライブラリ、内部ライブラリを別途インフラなしに依存として使える。

Leiningen は死んだか 否。Leiningen は依然として大きな市場を持つ。lein コマンドで repltestuberjar まで一行で終わる。学習曲線がより緩やかで、project.clj はデータではなくコードなのでマクロでより柔軟だ。欠点: 起動が遅く(JVM + Lein 起動約3秒)、Maven 中心なので Git 座標のような機能がぎこちない。

意思決定ガイド

  • 新プロジェクト + ライブラリ多様性重視 → deps.edn
  • 既存 Leiningen プロジェクト維持 → lein のまま
  • ライブラリ配布 → 両方可能だが deps.edn + build.clj (tools.build) 組み合わせが徐々に標準

tools.build build.clj というビルドスクリプトを Clojure で書く。Makepackage.json scripts に似ているが、すべて Clojure だ。

;; build.clj の一部
(ns build
  (:require [clojure.tools.build.api :as b]))

(def lib 'com.example/my-lib)
(def version "0.1.0")
(def class-dir "target/classes")

(defn clean [_]
  (b/delete {:path "target"}))

(defn jar [_]
  (b/write-pom {:class-dir class-dir
                :lib lib
                :version version})
  (b/jar {:class-dir class-dir
          :jar-file (format "target/%s-%s.jar" (name lib) version)}))

clj -T:build jar で呼び出す。すべてのビルド工程が Clojure 関数だ。


第3章 · Babashka 1.4 — シェルに入った Clojure

Babashka は Michiel Borkent(borkdude)が作った GraalVM ネイティブイメージにコンパイルされた Clojure インタプリタ だ。2026年5月時点で 1.4.x が安定版で、起動速度は 20〜30ms にすぎない。Python(約50ms)、Bash スクリプト(約10ms)と競合できる水準だ。

なぜシェルスクリプトに Clojure か 3つの理由。

  1. データ処理 — JSON、EDN、CSV、YAML がすべてファーストクラス市民。jq よりも表現力が高い。
  2. エラー処理 — Bash の set -e は危険。Clojure の例外と try/catch で堅牢なスクリプト。
  3. 可搬性bb バイナリ一つでどこでも同じコードが動く。

実例

#!/usr/bin/env bb

(require '[babashka.curl :as curl]
         '[cheshire.core :as json])

(defn fetch-github-stars [repo]
  (-> (curl/get (str "https://api.github.com/repos/" repo))
      :body
      (json/parse-string true)
      :stargazers_count))

(println "Stars:" (fetch-github-stars "clojure/clojure"))

bb script.clj または chmod +x して直接実行。JVM なしで動く。

bb tasks bb.edn ファイルにタスクを宣言する。npm run に似た感覚だが、Clojure 全体を使える。

;; bb.edn
{:tasks
 {test     (shell "clj -X:test")
  build    (shell "clj -T:build jar")
  deploy   {:depends [build]
            :task (shell "clj -T:build deploy")}
  clean    (shell "rm -rf target")}}

bb test, bb build, bb deploy のように呼び出す。:depends でタスク依存を宣言できる。

nbb — Node Babashka Node.js ランタイム上で動く Babashka。npm パッケージをそのまま使える。Node エコシステムを Clojure 風の短いスクリプトで扱いたいときに。

;; nbb から npm パッケージを呼び出し
(require '["fs" :as fs])
(println (fs/readdirSync "."))

squint — CLJS to JS コンパイルなしに Clojure 風構文を JS に直接変換。JSX 内でも使える。小さなツールで徐々に人気を集めている。

Babashka は「Python を置き換えようとしているのではなく、Bash を置き換えたい」と borkdude が言ったことがある。2026年にその野心は十分現実的だ。


第4章 · ClojureScript と shadow-cljs 2.x — npm エコシステムのフルアクセス

ClojureScript は Clojure コードを JavaScript にコンパイルするコンパイラだ。2026年時点で ClojureScript 開発の約80%は shadow-cljs をビルドツールに使う。Thomas Heller が作ったこのツールの核心価値は npm 統合 だ。

shadow-cljs 設定例

;; shadow-cljs.edn
{:source-paths ["src"]
 :dependencies [[reagent "1.2.0"]
                [re-frame "1.4.0"]
                [metosin/reitit-frontend "0.7.0"]]
 :builds
 {:app {:target :browser
        :modules {:main {:init-fn my-app.core/init}}
        :output-dir "public/js"
        :asset-path "/js"
        :devtools {:after-load my-app.core/reload!
                   :http-root "public"
                   :http-port 8080}}}}

npx shadow-cljs watch app で起動するとホットリロード、REPL、ビルドが同時に動く開発サーバーが立ち上がる。ビルドは esbuild ベースで速い。

npm パッケージを直接使う shadow-cljs の決定的な利点だ。package.json にパッケージを追加すれば、ClojureScript から即座に import できる。

(ns my-app.charts
  (:require ["chart.js" :as Chart]
            ["d3" :as d3]))

(defn render-chart [el data]
  (Chart/new el (clj->js {:type "bar"
                          :data data})))

["chart.js" :as Chart] — 文字列ライブラリ名が鍵。通常の Clojure 依存と npm パッケージを同じ require ブロックで混在できる。

Reagent — React ラッパーの古典 Reagent は React 上で最も古い ClojureScript ラッパーだ。Hiccup 構文で React コンポーネントを書く。

(ns my-app.ui
  (:require [reagent.core :as r]))

(defn counter []
  (let [n (r/atom 0)]
    (fn []
      [:div
       [:p "Count: " @n]
       [:button {:on-click #(swap! n inc)} "+1"]])))

[:div ...] のようなベクタが React element になる。r/atom は mutable な状態を表現し、変更時に自動的に再レンダリングされる。React 18 の並行機能までサポート。

Helix — 新しい React ラッパー Helix はフック優先設計。defnc マクロで関数コンポーネントを定義する。

(ns my-app.helix-ui
  (:require [helix.core :refer [defnc $]]
            [helix.hooks :as hooks]
            [helix.dom :as d]))

(defnc Counter []
  (let [[n set-n] (hooks/use-state 0)]
    (d/div
      (d/p "Count: " n)
      (d/button {:on-click #(set-n inc)} "+1"))))

$ マクロで他のコンポーネントをレンダリング。React Hooks と1:1で対応する。JSX より綺麗だという評が多い。

UIx 2 — 最もモダンな選択 UIx 2 は Helix と似た哲学だが、より速いレンダリング最適化を強調する。SSR(server-side rendering)サポート、React Server Components 互換が作業中。2026年の新規 ClojureScript プロジェクトの約30%が UIx 2 を選ぶ。

(ns my-app.uix-ui
  (:require [uix.core :refer [defui $]]
            [uix.dom]))

(defui counter []
  (let [[n set-n] (uix.core/use-state 0)]
    ($ :div
      ($ :p "Count: " n)
      ($ :button {:on-click #(set-n inc)} "+1"))))

第5章 · re-frame 1.4 — 大規模 SPA の状態管理の答え

Reagent でカウンターは作れる。しかし画面が100枚ある SPA で atom を複数のコンポーネントに撒くとデバッグが地獄になる。re-frame はその答えだ。Day8 チームが作ったこのライブラリは ClojureScript の事実上の標準状態管理だ。

re-frame のコアモデル

  1. app-db — すべての状態を保持する単一の大きなマップ
  2. events — ユーザー操作を表すキーワード(:user/login:cart/add-item)
  3. handlers — event を受けて app-db を変換する純粋関数
  4. subscriptions — app-db から画面が必要なデータを抜き出す関数
  5. effects — 外界との相互作用(HTTP、localStorage、タイマー)
(ns my-app.events
  (:require [re-frame.core :as rf]))

;; イベントハンドラ
(rf/reg-event-db
 :user/login-success
 (fn [db [_ user]]
   (assoc db :current-user user)))

;; サブスクリプション
(rf/reg-sub
 :user/current
 (fn [db _]
   (:current-user db)))

;; コンポーネントで使用
(defn user-panel []
  (let [user @(rf/subscribe [:user/current])]
    [:div "Hello, " (:name user)]))

;; イベントディスパッチ
(rf/dispatch [:user/login-success {:name "Min-yong Kim"}])

なぜ re-frame か 3つの理由。

  1. タイムトラベルデバッグ — re-frame-10x ライブラリですべての event をトレース。任意の時点の状態に巻き戻せる。
  2. 純粋関数優先 — handler が純粋関数なのでテストしやすい。
  3. エフェクト隔離 — HTTP 呼び出しのような副作用が明示的なので、テストとモックが綺麗。

re-frame 1.4 の変化

  • インターセプタチェーン最適化 — 大規模アプリで30%高速なディスパッチ
  • reg-fx への非同期エフェクトサポート
  • Devtools 統合強化 — Chrome Devtools パネルで event トレース

「Reagent + re-frame は React + Redux の Clojure 版だ。しかし Redux がボイラープレート地獄なのに対し、re-frame はマクロで同じ仕事をより短くやる。」 — Day8 チーム公式まとめ。


第6章 · Pathom 3 — グラフクエリの新標準

REST や GraphQL を使えば、クライアントが必要なデータをサーバーに要求する。しかしデータが複数のバックエンド(DB、外部 API、キャッシュ)に散らばっているとき、「このデータをどう集めるか」は常にバックエンドの悩みだ。Pathom 3 はこの問題をグラフリゾルバ方式で解く。

Pathom 3 のモデル 各データをどう取得するかを resolver で宣言する。クライアントは EQL(EDN Query Language)で必要なデータを要求し、Pathom がリゾルバグラフを探索して答えを集める。

(require '[com.wsscode.pathom3.connect.indexes :as pci]
         '[com.wsscode.pathom3.connect.operation :as pco])

;; リゾルバ — user-id で user 情報を取得
(pco/defresolver user-by-id [{:keys [user-id]}]
  {::pco/output [:user/name :user/email]}
  (let [user (db/find-user user-id)]
    {:user/name (:name user)
     :user/email (:email user)}))

;; リゾルバ — user-id で注文リストを取得
(pco/defresolver user-orders [{:keys [user-id]}]
  {::pco/output [:user/orders]}
  {:user/orders (db/find-orders-by-user user-id)})

(def env (pci/register [user-by-id user-orders]))

;; クライアントはグラフクエリで要求
(p.eql/process env
  {:user-id 42}
  [:user/name :user/email :user/orders])
;; => {:user/name "Min-yong" :user/email "..." :user/orders [...]}

Pathom が勝手に2つのリゾルバを呼び、結果をマージする。クライアントはデータ出所を知らない。

なぜ良いか

  • バックエンドを段階的にリファクタリングできる。リゾルバ内部を変えてもクライアントクエリはそのまま。
  • N+1 問題を Pathom が自動でバッチ処理。
  • GraphQL と違ってスキーマ定義がコードと一体化。

誰が使うか Fulcro フルスタックフレームワークのバックエンド標準。Nubank の一部マイクロサービスが Pathom でデータ集約レイヤーを構成する。


第7章 · Datomic Pro · Cloud — 時間をデータに

Datomic は Rich Hickey 自身が設計したデータベースだ。Cognitect が作り、2023年から Datomic Pro ライセンスが無償化 されて参入障壁が消えた。2026年時点で Datomic は2つの製品群がある。

  • Datomic Pro — 自己ホスト、無償。PostgreSQL/DynamoDB/Cassandra などをストレージに使用。
  • Datomic Cloud — AWS 上のサーバーレスマネージド、有償。

Datomic のコアアイデア

  1. immutable — データを絶対に上書きしない。すべての変更が append-only。
  2. bitemporal — トランザクション時間(いつ記録されたか)と valid 時間(いつ事実だったか)を別々に追跡。
  3. EAV モデル — entity-attribute-value のトリプル。RDF に似ている。
  4. 読み書きの分離 — peer/client がインデックスをローカルメモリに取り込んでクエリ。transactor のみ直列化。
;; スキーマ定義
(def schema
  [{:db/ident :user/email
    :db/valueType :db.type/string
    :db/cardinality :db.cardinality/one
    :db/unique :db.unique/identity}
   {:db/ident :user/name
    :db/valueType :db.type/string
    :db/cardinality :db.cardinality/one}])

(d/transact conn {:tx-data schema})

;; データ挿入
(d/transact conn
  {:tx-data [{:user/email "min@example.com"
              :user/name "Min-yong Kim"}]})

;; Datalog クエリ
(d/q '[:find ?name
       :in $ ?email
       :where
       [?u :user/email ?email]
       [?u :user/name ?name]]
     (d/db conn)
     "min@example.com")
;; => [["Min-yong Kim"]]

bitemporal — タイムトラベルクエリ

;; 「2025年12月1日時点の」DB で同じクエリ
(d/q '[:find ?name ...]
     (d/as-of (d/db conn) #inst "2025-12-01"))

;; あるエンティティのすべての変更履歴
(d/history (d/db conn))

なぜ使うか

  • 監査(audit)要件が強い金融・医療システムに適合。
  • スキーママイグレーションなしで新しい属性を追加可能。
  • 読み込みキャッシュが peer にあり read-heavy ワークロードに強い。

誰が使うか Nubank のほぼすべてのバックエンドマイクロサービスが Datomic を使う(自社インフラ)。会計・法務・医療ドメインで採用が増えている。

Datomic は「DB は関数型であるべき」という Rich Hickey の主張の結晶だ。高価ではない、無料だ。しかし思考の転換が必要だ。


第8章 · XTDB 2.0 — bitemporal + SQL-first

XTDB(旧名 Crux)はイギリス JUXT チームが作った bitemporal データベースだ。2026年時点で XTDB 2.0 が安定版で、1.x と比較して大きな変化がある。

1.x → 2.0 の違い

  • カラムナストレージ(Apache Arrow ベース)で分析クエリ性能が大幅向上
  • SQL をファーストクラス市民に — もはや Datalog だけを強要しない
  • オブジェクトストレージ(S3)にデータを保存 — コスト削減
-- XTDB 2.0 — 標準 SQL でタイムトラベル
SELECT name, email
FROM users
FOR VALID_TIME AS OF DATE '2025-12-01'
WHERE name LIKE 'Min%';

-- トランザクション時間と valid 時間を両方指定
SELECT *
FROM users
FOR SYSTEM_TIME AS OF TIMESTAMP '2026-01-15 10:00:00'
FOR VALID_TIME AS OF DATE '2025-12-01';

Clojure からも呼び出せる。

(require '[xtdb.api :as xt])

(xt/q node
  '(from :users [name email]))

;; SQL も同等
(xt/q node "SELECT name, email FROM users")

なぜ XTDB か vs Datomic

  • XTDB は SQL 互換 が強み。PostgreSQL ユーザーが移行しやすい。
  • Datomic は Datalog 優先 で、より深いグラフクエリに強い。
  • XTDB 2.0 のカラムナストレージは分析ワークロード(OLAP)に強い。
  • Datomic はトランザクショナルワークロード(OLTP)により最適化。

Datalevin と Datahike 組み込み/オンデバイスシナリオ。Datalevin は LMDB ベースの組み込み Datalog DB。Datahike は IPFS もバックエンドに使える分散フレンドリーな Datomic ライク DB。モバイルや Electron アプリに埋め込みやすい。


第9章 · next.jdbc · HoneySQL — モダンな SQL スタック

Datomic や XTDB がすべてのシナリオに合うわけではない。既存の PostgreSQL・MySQL をそのまま使う場面が多い。2026年の Clojure 標準 JDBC ライブラリは next.jdbc で、SQL DSL は HoneySQL だ。

next.jdbc の基本

(require '[next.jdbc :as jdbc])

(def db {:dbtype "postgresql"
         :dbname "myapp"
         :user "postgres"
         :password "secret"})

;; クエリ
(jdbc/execute! db ["SELECT id, name FROM users WHERE id = ?" 42])
;; => [{:users/id 42 :users/name "Min-yong"}]

;; トランザクション
(jdbc/with-transaction [tx db]
  (jdbc/execute! tx ["INSERT INTO users (name) VALUES (?)" "New User"])
  (jdbc/execute! tx ["INSERT INTO accounts (user_id, balance) VALUES (?, ?)"
                     42 0]))

next.jdbc は clojure.java.jdbc の後継で、より速くより小さな API だ。結果を自動的にキーワードキーのマップに変換する。

HoneySQL — SQL をデータに

(require '[honey.sql :as sql])

(sql/format
  {:select [:id :name :email]
   :from [:users]
   :where [:and
           [:= :status "active"]
           [:> :age 18]]
   :order-by [[:created-at :desc]]
   :limit 10})
;; => ["SELECT id, name, email FROM users
;;      WHERE status = ? AND age > ? ORDER BY created_at DESC LIMIT ?"
;;     "active" 18 10]

EDN マップで SQL を表現する。動的に条件を合成したり、一部の節を抜き出して関数にしたりしやすい。ORM ではなく データ優先 SQL ジェネレータ だ。


第10章 · Ring · Compojure · Reitit — HTTP サーバー三羽烏

Clojure バックエンドはほぼすべて Ring を基盤にする。Ring は HTTP リクエスト/レスポンスを単純なマップで表現する抽象化だ。その上に複数のルーティングライブラリが乗る。

Ring の基本 リクエストはマップ、レスポンスもマップ、ハンドラは関数。

(defn handler [request]
  {:status 200
   :headers {"Content-Type" "text/plain"}
   :body "Hello, world"})

;; Jetty サーバーで実行
(require '[ring.adapter.jetty :as jetty])
(jetty/run-jetty handler {:port 3000})

ミドルウェアはハンドラを包む高階関数。

(defn wrap-logging [handler]
  (fn [request]
    (println "Request:" (:uri request))
    (handler request)))

(jetty/run-jetty (wrap-logging handler) {:port 3000})

Compojure — 古典的なルータ

(require '[compojure.core :refer [defroutes GET POST]])

(defroutes app
  (GET "/" [] "Home")
  (GET "/users/:id" [id] (str "User " id))
  (POST "/users" req (create-user req)))

小さなアプリには十分だが、大規模アプリではルート定義がコードなので静的解析が難しい。

Reitit — データ優先ルータ

(require '[reitit.ring :as ring]
         '[reitit.coercion.malli :as rcm])

(def app
  (ring/ring-handler
    (ring/router
      [["/api"
        ["/users"
         {:get  {:handler list-users
                 :parameters {:query [:map [:limit int?]]}}
          :post {:handler create-user
                 :parameters {:body [:map [:name string?] [:email string?]]}}}]
        ["/users/:id"
         {:parameters {:path [:map [:id int?]]}
          :get {:handler get-user}}]]]
      {:data {:coercion rcm/coercion
              :middleware [...]}})))

ルートが データ(ベクタ+マップ)だ。ミドルウェア、入力検証(coercion)、OpenAPI スペック生成を自動化できる。2026年の新規 API プロジェクトの約60%が Reitit を選ぶ。

Pedestal Cognitect が作った代替。インターセプタチェーンモデルで非同期・ストリーミングをファーストクラスとして扱う。Reitit より学習曲線が急だが、複雑なワークフロー(例: SSE、大ファイルアップロード)に強い。


第11章 · Aleph · Manifold · core.async — 非同期とストリーム

Clojure の並行性モデルは3つの軸に分かれる。

  1. core.async — Go チャネルスタイル。CSP モデル。
  2. Manifold — deferred とストリーム。より関数型寄り。
  3. Aleph — Netty 上の非同期 HTTP/TCP サーバー。Manifold を使う。

core.async

(require '[clojure.core.async :as async :refer [go chan <! >!]])

(let [c (chan 10)]
  (go (>! c "hello")
      (>! c "world"))
  (go (println (<! c))
      (println (<! c))))

go ブロックは軽量コルーチン、<!/>! はチャネルから受け取り送信する演算。JVM 上で Go のようなコードが動く。

Manifold

(require '[manifold.deferred :as d]
         '[manifold.stream :as s])

;; deferred は promise + future の一般化
(def result (d/deferred))
(d/chain result inc inc inc)  ; 関数チェイン
(d/success! result 1)          ; => 4

;; stream は非同期シーケンス
(def s (s/stream))
(s/consume #(println "got:" %) s)
(s/put! s 42)  ; => "got: 42" 出力

Aleph サーバー

(require '[aleph.http :as http])

(defn handler [req]
  ;; deferred を返すと Aleph が非同期で処理
  (d/future
    (Thread/sleep 100)
    {:status 200 :body "done"}))

(http/start-server handler {:port 3000})

Aleph は Netty 上に乗っており、1台のサーバーで数万の同時接続を扱う。WebSocket、SSE、gRPC も自然だ。

core.async が Go のチャネルなら、Manifold は Scala の Future + Akka Stream の Clojure 表現だ。両者は補完関係で、一つのアプリで一緒に使える。


第12章 · Spec · Malli · Schema — 検証の3つの分岐

Clojure は動的型付けだが、データ形(shape)を検証するツールが豊富だ。3つのライブラリが競う。

clojure.spec — 公式の答え

(require '[clojure.spec.alpha :as s])

(s/def :user/email (s/and string? #(re-matches #".+@.+" %)))
(s/def :user/age (s/and int? #(<= 0 % 150)))
(s/def :user/user (s/keys :req-un [:user/email :user/age]))

(s/valid? :user/user {:email "min@example.com" :age 30})
;; => true

(s/explain :user/user {:email "bad" :age 30})
;; => :email failed: re-matches predicate

s/keys でマップ形を定義し、s/and/s/or で組み合わせる。Spec は 関数の引数・戻り値の仕様 もサポートする。

(s/fdef calc-tax
  :args (s/cat :amount pos-int? :rate (s/and number? pos?))
  :ret pos-int?)

stest/instrument で有効化すれば、関数呼び出し時に自動で検証される。

Malli — データ優先 + 高速

(require '[malli.core :as m])

(def User
  [:map
   [:email [:re #".+@.+"]]
   [:age [:int {:min 0 :max 150}]]])

(m/validate User {:email "min@example.com" :age 30})
;; => true

(m/explain User {:email "bad" :age 30})
;; => {:errors [...]} 詳細エラー

Malli は スキーマがデータ(EDN) なので直列化・送信が簡単で、Reitit の入力検証、OpenAPI スペック生成、自動ドキュメント化に自然に繋がる。2026年の新規プロジェクトの多くが Malli を選ぶ。

Plumatic Schema — 古典 最も古いライブラリ。マクロベースでコンパイル時検証が可能。レガシープロジェクトに多く残る。

どう選ぶか

  • 公式ツールで行きたい → Spec
  • データ優先 + Reitit・Malli 統合 → Malli
  • レガシー互換 → Schema

第13章 · Mount · Integrant · Component — DI/ライフサイクル

大きなシステムは起動順序(DB 接続 → キャッシュ → HTTP サーバー → バックグラウンドジョブ)と終了順序が重要だ。Clojure にはこれのための3つのライブラリがある。

Mount — 最もシンプル

(require '[mount.core :as mount])

(mount/defstate db
  :start (open-connection "jdbc:...")
  :stop (close-connection db))

(mount/defstate server
  :start (start-server {:port 3000})
  :stop (stop-server server))

(mount/start)  ; すべて開始
(mount/stop)   ; 逆順で終了

グローバル状態を使うが非常にシンプル。小規模プロジェクトに適合。

Component — Stuart Sierra の古典

(defrecord Database [config conn]
  component/Lifecycle
  (start [this] (assoc this :conn (open-connection config)))
  (stop [this] (close-connection conn) (assoc this :conn nil)))

(def system
  (component/system-map
    :db (->Database db-config nil)
    :server (component/using (->Server {}) [:db])))

依存関係を明示的に宣言する。テストでコンポーネントを差し替えやすい。

Integrant — データ優先 Component

(require '[integrant.core :as ig])

(def config
  {:db/connection {:url "jdbc:..."}
   :server/jetty  {:db (ig/ref :db/connection) :port 3000}})

(defmethod ig/init-key :db/connection [_ {:keys [url]}]
  (open-connection url))

(defmethod ig/init-key :server/jetty [_ {:keys [db port]}]
  (start-server {:db db :port port}))

(def system (ig/init config))
(ig/halt! system)

設定が EDN データなので、環境別の設定ファイルとして分離可能。Reitit と自然に組み合わさる。2026年の新規プロジェクトで最も多い選択。


第14章 · テスト — clojure.test から generative まで

clojure.test — 標準

(require '[clojure.test :refer [deftest is testing]])

(deftest user-creation-test
  (testing "valid input creates user"
    (is (= "Min-yong" (:name (create-user {:name "Min-yong"})))))
  (testing "missing email throws"
    (is (thrown? Exception (create-user {})))))

基本同梱。JUnit に似た感触だがより関数型。

Kaocha — モダンランナー clojure.test の上に乗せるランナー。カラー出力、ウォッチモード、プラグインシステム、JUnit XML レポート。

clj -M:test  # または bb test

tests.edn で設定。CI で決定的な出力を出すのに良い。

Eftest clojure.test 互換。ウォッチモードと並列実行に強い。

clojure.test.check — Property-based testing

(require '[clojure.test.check :as tc]
         '[clojure.test.check.generators :as gen]
         '[clojure.test.check.properties :as prop])

(def reverse-twice-is-identity
  (prop/for-all [v (gen/vector gen/int)]
    (= v (reverse (reverse v)))))

(tc/quick-check 100 reverse-twice-is-identity)
;; => 100個のランダム入力で検証

QuickCheck の Clojure 移植。入力をランダムに生成して性質を検証する。

clojure.spec.test — Spec と統合

(require '[clojure.spec.test.alpha :as stest])

(stest/check `calc-tax)
;; => spec fdef で定義された関数を generative にテスト

Spec 仕様があれば自動的に generative テストが回る。


第15章 · エディタ4強 — Cursive · Calva · CIDER · Conjure

Clojure 開発は REPL が核心 だ。コードをファイルに保存して再起動するのではなく、稼働中の REPL に式を一つずつ送って即座に評価する。だからエディタ選択が他の言語より決定的だ。

Cursive — IntelliJ IDEA プラグイン 最も完成度の高い商用オプション。コードインテリジェンス(自動補完、リファクタリング、静的解析)が強力。大規模プロジェクトで正確なナビゲーションとリファクタリングが必要なときに圧倒的。個人ライセンス年99ドル、商用は別料金。無償の EAP ビルドもある。

Calva — VS Code 拡張 無償、オープンソース、最も使われるエディタ。REPL 統合、paredit 編集、インライン評価結果表示、jack-in 自動化。VS Code ユーザーなら第一選択。2026年の Clojure ユーザーの約45%が Calva を使うという非公式調査。

CIDER — Emacs 最も古く最も強力。REPL 統合、デバッガ、トレース、マクロ段階展開可視化まですべてファーストクラス。Emacs をすでに使っているならほぼデフォルト。

Conjure — Neovim Neovim ユーザー向けの答え。tmux フレンドリー。軽量だがすべてのコア機能を備える。

ファイル → REPL の流れ Cursive・Calva・CIDER すべて同じ流れ。ファイルを開き、「このフォームを REPL で評価」キー(Cmd-EnterCmd-Shift-Enter など)を押すと式が REPL に送信される。関数を修正して再評価すれば、即座に新しい定義が稼働中のシステムに反映される。サーバーを再起動しない。

「REPL にコードを送るその瞬間が Clojure を使う最大の理由だ。コンパイル・実行・停止のサイクルがない。コードは常に生きている。」 — Bruce Hauman, Figwheel 作者。


第16章 · REPL 駆動開発 — なぜ LLM 時代に最も適しているか

REPL 駆動開発(REPL-driven development)は Clojure 文化の心臓だ。核心のアイデアはシンプルだ。

  1. REPL を常に立ち上げておく。
  2. コードはファイルにあるが、実行は REPL で一つの式ずつ。
  3. 結果を見て、コードを修正し、再評価する。
  4. 満足したらそのコードをファイルに残し、次へ進む。

なぜ LLM 時代により輝くか LLM はコードブロックを生成する。人間がそれを検証する必要がある。検証方法は2つ。

  • 従来の方法: ファイルに貼り付け、ビルド/テストを回し、結果を見る。サイクルが長い(数十秒〜数分)。
  • REPL の方法: LLM が生成した式を REPL に直接評価する。即座に結果が出る。間違っていたら再度聞き、再評価する。

Clojure はこのワークフローに本質的に合う。データが EDN で表現可能なので、LLM が生成したデータを REPL にそのまま貼って評価できる。マクロシステムが強いので、LLM がドメイン特化コードを短く表現できる。

実戦 LLM + REPL ワークフロー

;; LLM に「ユーザーリストから30代だけフィルタリングする関数を書け」と要求
;; LLM の答えを REPL で評価:
(defn users-in-30s [users]
  (filter #(<= 30 (:age %) 39) users))

;; 即座にテスト
(users-in-30s [{:name "A" :age 25}
               {:name "B" :age 35}
               {:name "C" :age 45}])
;; => ({:name "B" :age 35})

;; よく動く。ファイルに保存。

長いビルドサイクルなしに LLM の応答をすぐに検証できる。2026年、Cursive・Calva 両方とも LLM の応答を REPL に直接送るショートカットをサポートする。


第17章 · GraalVM Native Image — Clojure をネイティブバイナリに

GraalVM は JVM バイトコードを ahead-of-time(AOT)コンパイルしてネイティブ実行ファイルを作る。Clojure プログラムを GraalVM Native Image でコンパイルすると起動速度が約20ms に落ちる(JVM の1〜2秒に対し)。

いつ有用か

  • CLI ツール(Babashka がまさにこのカテゴリ)
  • AWS Lambda のような cold-start が重要なサーバーレス
  • 小さなマイクロサービス(例: 単一ヘルスチェックエンドポイント)

限界

  • リフレクション、動的クラスローディングに制約がある。Clojure は動的言語なので一部パターンが動かない。
  • ビルド時間が非常に長い(分単位)。
  • メモリフットプリントは小さいが、ピーク性能は JIT より低い場合がある。

実例 Babashka 自体が最大の成功事例。bb バイナリは GraalVM でコンパイルされた約80MB の静的バイナリ。起動速度約20ms、メモリ約30MB。Python より軽く動く。

自分のアプリを native-image にするときは、org.clj-easy/graal-build-time のようなヘルパーライブラリと clj.native-image のようなビルドツールを使う。JVM 互換性オプション(--initialize-at-build-time など)をうまく設定する必要がある。


第18章 · Nubank 事例 — 1億ユーザーを Clojure で

Nubank は Clojure 世界最大のプロダクション事例だ。ブラジル発のデジタル銀行で、2026年時点で 1億1,000万顧客、マイクロサービス5,000以上、日次トランザクション数十億件 を処理する。バックエンドはほぼすべて Clojure だ。

なぜ Clojure を選んだか 共同創業者で CTO の Edward Wible が説明している(公開講演多数)。3つの理由。

  1. 関数型 + 不変データ — 金融データは任意の修正が起きてはならない。immutable が自然にそのセーフティネットを提供する。
  2. Datomic — すべての取引履歴を bitemporal で保持する必要がある。Datomic のモデルが正にマッチ。
  3. REPL 駆動開発 — 本番デバッグに REPL を立ち上げてライブデータを調査する。取引事故が起きたとき即座に診断可能。

アーキテクチャ概要

  • すべてのマイクロサービスが Clojure(一部 Kotlin/Go もあり)
  • Datomic がメイン DB(自社 Pro ライセンス、AWS DynamoDB バックエンド)
  • Kafka でマイクロサービス間イベントストリーム
  • Pedestal/Aleph ベースの HTTP サーバー
  • Schema(レガシー)と Malli(新規)でデータ検証
  • 自社開発の Pathom ライクなグラフクエリレイヤー

チーム運営 約2,000人のエンジニアが Clojure を使う。新規採用時に Clojure 経験は必須ではない — 自社トレーニングブートキャンプで教える。関数型思考があれば素早く適応するという方針。

パフォーマンス

  • p99 応答時間: 50ms 未満(ほとんどのエンドポイント)
  • 可用性: 99.99% 以上
  • マイクロサービス1個当たり平均: インスタンス約5個、メモリ約512MB

「Clojure を選んだのは事業に最も良い決定の一つだった。シンプルさが私たちを速くした。」 — Edward Wible, Nubank CTO。


第19章 · 韓国・日本コミュニティ — どこまで来たか

Clojure Korea ソウル中心に活動するコミュニティ。Slack チャンネル clojure-kr、定期ミートアップ、ペアプログラミングセッション。Mun-yong Kim など1世代の開発者が積極的に活動する。Kakao・Naver 内部でも一部チームが Clojure を使う(詳細な公開資料は少ないが)。韓国語資料としては Wikibooks/Insight の翻訳書、そして GitHub の韓国語チュートリアルがある。

Clojure Tokyo / Clj-jp 日本コミュニティは韓国より活動がより活発だ。東京定期ミートアップ、福岡・大阪支部、年1回のカンファレンス Clj-jp Conf。Drip(酒類)、Cookpad(料理レシピ)、Recruit など一部の日本企業が本番で使う。日本語の学習資料が豊富だ。

アジアカンファレンス

  • Clojure/conj — 米国、最大のカンファレンス(年1回)
  • Clojure/north — カナダ
  • re:Clojure — イギリス
  • EuroClojure — ヨーロッパ
  • Clj-jp Conf — 日本

2026年には韓国でも小規模な Clojure カンファレンスを復活させようとする動きがある。


第20章 · 2026年から始める人へのスタック推奨

背景別に整理する。

Java/Kotlin 出身

  • Clojure 1.12 + Leiningen → 馴染みのあるビルドツールで開始
  • IntelliJ IDEA + Cursive
  • Ring + Compojure(小規模アプリ)または Reitit(中・大規模)
  • PostgreSQL + next.jdbc + HoneySQL
  • 最初の本: "Programming Clojure (4th edition)"

JavaScript/TypeScript 出身

  • ClojureScript + shadow-cljs
  • VS Code + Calva
  • Reagent + re-frame(検証済みの安定性)または UIx 2(モダン)
  • npm パッケージをそのまま持ってきて使うところから
  • 最初の本: "Learn ClojureScript"(無償、オンライン)

Python/Ruby 出身

  • Babashka でシェルスクリプトから開始
  • VS Code + Calva
  • Datomic Pro または SQLite + next.jdbc
  • REPL 駆動開発の学習が最大の mind shift
  • 最初の資料: 公式サイト "Getting Started"

Lisp 経験者(Scheme, CL)

  • 学習が非常に速い
  • Cursive または Emacs+CIDER
  • 関数型がより強調されるという点だけ適応
  • マクロシステムは Common Lisp に似ている

共通学習経路

  1. REPL を起動して一行ずつ実験lein repl または clj
  2. データ操作の練習mapfilterreduceintoupdate-inselect-keys
  3. 状態管理atomrefagent の違い
  4. シーケンス抽象 — lazy seq、transducer
  5. マクロ — 最後に

「Clojure を1週間で学んだ」と言う人がいる。実はそれは可能だ。しかしその後の6か月が本当の始まりだ。関数型思考は時間が必要だ。


第21章 · よく受ける疑問に答える

Q: 動的型付けなのでランタイムで壊れないか? A: 部分的に正しい。しかし Clojure はデータ形を EDN と Spec/Malli で仕様化する。関数境界で検証し、内部は動的に扱う。大規模システムでもよく動く — Nubank が証明している。

Q: 人材プールが小さくないか? A: 小さい。しかし 残っている人材が強い。Clojure 採用は関数型思考を持つ人をフィルタリングする。平均的により上級なチームになるという報告が一貫している。Nubank の採用データ: 離職率が他のフィンテック平均の半分。

Q: 採用が難しくないか? A: 2つの答え。(1) 他言語出身を採用して教えるのが正解。Clojure は素早く学べる。(2) Clojure を使うという事実自体が良いエンジニアを引きつける磁石になる。

Q: パフォーマンスは? A: JVM 上で動くので JIT コンパイル済みコードは Java 水準。ホットパスでボクシング回避、型ヒントなど最適化可能。Nubank の p99 50ms は一般的な Java・Go バックエンドと同等かそれ以上。

Q: 学習曲線? A: 急な部分が2か所。(1) 括弧と prefix 表記法への適応 — 通常1週間。(2) 関数型思考 — 平均3か月。その後は平坦。

Q: Java ライブラリ呼び出しは? A: ファーストクラス市民。(.method obj arg) または 1.12 から Class/.method 形。Java ライブラリのほとんどを使える。JVM ホストの最大の利点。

Q: Clojure が使えない場合は? A: 3つ。(1) GC 一時停止を絶対に耐えられない hard real-time。(2) メモリフットプリントが非常に小さくなければならない組み込み(ただし Babashka で一部解決)。(3) チーム全体が関数型に拒否感があるとき。


第22章 · 2026年以降の方向

予想される流れ

  1. AI/LLM 統合強化 — REPL 駆動開発と LLM の相性が良く、IDE 統合が深まる。Cursive・Calva が Claude・Cursor のようなツールとより近くなる。
  2. ClojureScript の復活 — UIx 2 と React Server Components の出会い、Bun・Deno のような新しいランタイムサポートが進行中。
  3. Babashka の領域拡大 — シェルスクリプト → CLI ツール → 小さなサーバーまで。nbb・squint とともに徐々に領域が広がる。
  4. Datomic vs XTDB の競争 — bitemporal DB 市場が拡大するにつれ、両陣営が発展を加速。
  5. GraalVM Native Image の安定化 — より多くの Clojure ライブラリが native-image 互換を保証。
  6. WebAssembly コンパイル — ClojureScript → WASM 実験が進行中。ブラウザ以外の使用可能性が開ける。

リスク要因

  • Rich Hickey の後継 — Hickey は2022年に Nubank から引退した。Cognitect チームがうまく引き継いでいるが、一人のビジョンが消えた後の長期的一貫性が試されている。
  • Datomic の未来 — Cognitect が Nubank に買収された後、Datomic のオープンソース化がどこまで進むか不透明。
  • 他の関数型言語との競争 — Elixir・Gleam・Roc などが新たに台頭。Clojure はどう差別化を維持するか。

楽観的シナリオ Nubank の成功が他のフィンテック・バイオ・ヘルスドメインに広がる。韓国・日本の大企業でも段階的採用。ClojureScript の React 統合がより滑らかになり、フロントエンド市場で意味あるシェア確保。


第23章 · 結論 — Clojure が生き残った理由

20年近く一貫性を保った言語は多くない。Rich Hickey の原則 — 「シンプルさは易しさよりも重要(simple is better than easy)」 — が Clojure のすべての決定の根底にある。その結果、Clojure はトレンドを追わず自分の道を行った。

それが生き残った理由だ。フィンテック、医療、会計、コンプライアンス — 正確性が速度より重要なドメイン で Clojure は絶対的だ。Nubank が1億ユーザーを支えるという事実は偶然ではない。

2026年に Clojure を始める人へ一言。

速く学ぼうとするな。REPL を立ち上げて、一つの式ずつ、ゆっくり身につけよ。 Clojure は一度に学ぶものではなく、一つの式ずつ育てていく言語だ。6か月後には他の言語に戻れなくなる。

幸運を。REPL を起動して始めよう。


References

  1. Clojure 公式サイト — https://clojure.org
  2. Clojure 1.12 Release Notes — https://github.com/clojure/clojure/blob/master/changes.md
  3. Rich Hickey, "Simple Made Easy" — https://www.youtube.com/watch?v=SxdOUGdseq4
  4. Rich Hickey, "Hammock Driven Development" — https://www.youtube.com/watch?v=f84n5oFoZBc
  5. Babashka 公式 — https://babashka.org
  6. Michiel Borkent, "Babashka: A native Clojure interpreter for scripting" — https://blog.michielborkent.nl
  7. ClojureScript 公式 — https://clojurescript.org
  8. shadow-cljs 公式 — https://github.com/thheller/shadow-cljs
  9. re-frame 公式 — https://day8.github.io/re-frame
  10. Reagent 公式 — https://reagent-project.github.io
  11. Helix 公式 — https://github.com/lilactown/helix
  12. UIx 2 公式 — https://github.com/pitch-io/uix
  13. Pathom 3 公式 — https://pathom3.wsscode.com
  14. Datomic 公式 — https://www.datomic.com
  15. XTDB 2.0 公式 — https://xtdb.com
  16. next.jdbc 公式 — https://github.com/seancorfield/next-jdbc
  17. HoneySQL 公式 — https://github.com/seancorfield/honeysql
  18. Reitit 公式 — https://github.com/metosin/reitit
  19. Pedestal 公式 — https://pedestal.io
  20. Aleph 公式 — https://github.com/clj-commons/aleph
  21. Manifold 公式 — https://github.com/clj-commons/manifold
  22. core.async 公式 — https://github.com/clojure/core.async
  23. clojure.spec 公式 — https://clojure.org/about/spec
  24. Malli 公式 — https://github.com/metosin/malli
  25. Integrant 公式 — https://github.com/weavejester/integrant
  26. Kaocha 公式 — https://github.com/lambdaisland/kaocha
  27. clojure.test.check 公式 — https://github.com/clojure/test.check
  28. Cursive 公式 — https://cursive-ide.com
  29. Calva 公式 — https://calva.io
  30. CIDER 公式 — https://docs.cider.mx
  31. Nubank Engineering Blog — https://building.nubank.com.br/tag/clojure
  32. Edward Wible, "Why Clojure?" — https://www.youtube.com/results?search_query=edward+wible+nubank+clojure
  33. State of Clojure 2024 Survey — https://clojure.org/news/2024/05/01/state-of-clojure-2024
  34. Clojure Korea Slack — https://clojurians.slack.com (#clojure-kr チャンネル)
  35. Clj-jp 公式 — https://clj-jp.org
  36. GraalVM Native Image — https://www.graalvm.org/native-image
  37. clj.native-image — https://github.com/taylorwood/clj.native-image
  38. Programming Clojure (4th ed) — https://pragprog.com/titles/shcloj4/programming-clojure-fourth-edition
  39. Learn ClojureScript (無料書籍) — https://www.learn-clojurescript.com
  40. ClojureVerse コミュニティフォーラム — https://clojureverse.org