
Rich Hickeyが2007年にClojureを世に送り出すまでの道のりを、時系列でたどります。彼が既存言語に対して抱いていた不満、状態管理と並行性への問題意識、そしてLispの伝統をJVM上で再構築するという決断の背景がわかります。主要バージョンの軌跡や、言語進化の節目を支えた追加機能を追いながら、長い沈黙の自己投資を経て、なぜClojureが「実用的なLisp」として独自のポジションを築けたのかを一本の物語として理解できます。
REPLを開いてprintlnで文字列を出力する、Clojureに触れる最初の一歩を踏み出します。短いメッセージを表示しながら、コンソールへの出力と評価結果(nil)の違い、そしてprn・println・print・pr-strの使い分けを体験します。最後は改行やタブのエスケープに触れ、pr-strでセーブデータ用の文字列を作り出す例まで動かして、文字列リテラルとエスケープといった基礎を最初に押さえます。
defを使ったトップレベル束縛で、Clojureにおける「変数」の扱い方を学びます。名前やステータスといった値を名前に束縛し、後からその値を参照したり組み合わせて一文を作ったりするコードを動かしながら、可変変数を持たないClojureの「再代入ではなく再束縛」という考え方を出力を通じて体感します。最後は複数の値を束縛して一枚のプロフィールカードを組み立てる演習で、defの構文と評価順序を定着させます。
整数・浮動小数・有理数・BigIntegerという、Clojureの豊富な数値型をREPLで実際に触ります。42・3.14・1/3・N接尾辞付きの大きな数を評価し、(type x)で型を確かめながら、1/3 + 1/6が誤差なく足し合わされることや、巨大な数をN接尾辞でBigIntとして扱う仕組みを目にします。最後は複利計算を有理数で書き、誤差なく結果が得られることを自分で確認します。
文字列・文字・キーワード・シンボルという、Clojureが扱うテキスト系・記号系の値を一通り体験します。ダブルクォートの文字列、バックスラッシュ記法の文字(\あ)、コロン始まりのキーワード(:name)、引用符付きシンボル('power)を順に評価し、それぞれの型と用途の違いを確かめます。str関数で日本語を連結し、キーワードがマップのキーになる例にも触れたうえで、四つの値を組み合わせて一枚のカードを完成させます。
Clojureにおけるtrue・false・nilの扱いと、ifでの「偽とみなされるもの」のルールを確実に押さえます。(if nil ...)・(if false ...)・(if 0 ...)・(if "" ...)・(if [] ...)を実行し、Clojureで偽となるのはfalseとnilだけ、0や空文字列・空コレクションですら真であることを目の当たりにします。boolean関数による明示変換も学び、年齢に応じてモードを切り替える式を書いて真偽判定を体に染み込ませます。
Clojureの根幹をなす設計思想を、コードを使わず図とテキストで読み解きます。Hickeyの「Simple Made Easy」で語られた「simple」と「easy」の区別、不変性を第一級に据える決断、そしてstate・identity・valueを切り分ける独自のモデルがわかります。なぜClojureがOOPの継承や可変オブジェクトを意図的に避けたのか、その判断が並行プログラミングや長期保守にもたらす利点を、Clojureを支える四本の柱とともに理解できます。
Clojureの前置記法(+ 1 2 3)に体を慣らします。加減乗除に加えてquot・rem・mod・inc・decや、可変長引数を取る加算をREPLで評価し、出力を確認します。複数の値が昇順かどうかをまとめて判定するチェーン比較や、=とidentical?の違いにも触れ、買い物の合計金額を求める演習を通じて、関数呼び出しが式そのものであるという感覚を養います。
条件分岐の三本柱、if・when・condを使い分けられるようになります。値で結果を返すif、副作用を伴う処理をまとめるwhen、複数の境界条件を整理するcondを、それぞれ動かしながら、ifが値を返すこと・whenがelse節を持たないこと・condが上から順に評価されることを体感します。気温に応じて装備を選ぶcond式を組み立て、条件の網羅性と順序の重要さを身につけます。
and・or・notが単なる真偽演算子ではなく、短絡評価を行い「最後に評価された値」を返すというClojureらしい振る舞いを学びます。(and 1 2 3)が3を、(or nil false :found)が:foundを返す様子を実行で確かめ、デフォルト値の指定や安全な値取り出しのイディオムへの応用を見ます。データから値が見つからないとき既定値を返す式を書き、orの実用パターンを自分のものにします。
Clojureで「ループ」を書く中心的な仕組み、loop/recurを習得します。1から指定した数までの累計をループで求めながら、recurがスタックを消費しない末尾呼び出しであることを理解し、続けて階乗関数で再帰ロジックを安全に表現する方法を身につけます。最後はフィボナッチ数列のn番目を返すloop/recur関数を書き、可変変数のない言語でどう状態を更新するかを掴みます。
値ではなく副作用(出力やI/O)を目的とした反復を書くための、doseqとdotimesを扱います。dotimesで回数を指定してメッセージを表示し、doseqでコレクションの要素を一つずつ出力しながら、両者が常にnilを返すこと、map・filterのような遅延シーケンスとは目的が異なることを理解します。二重バインディングのdoseqで九九の表を出力する演習で、Clojureにおける「副作用のループ」の自然な書き方を覚えます。
ClojureがJVM上に築かれたことの戦略的な意味を、エコシステム全体図とともに俯瞰します。Java相互運用や巨大なライブラリ資産へのアクセス、そして多様な実行ターゲットの広がりまでを見渡せます。主要ビルドツールの選び分け、エディタとREPL支援の選択肢、主要Webフレームワークの役割と関係を整理し、自分の用途に合った選択を素早く下せるようになります。
名前付き関数を定義する最も基本的な方法、defnを学びます。二つの数を組み合わせて結果を返す関数、円の面積を使った計算を順に定義して呼び出しながら、docstring・引数ベクタ・本体式という三要素の役割を出力で確認します。関数呼び出しもまた式であることを見たうえで、税込み価格を返すtax-included関数を自分で定義し、複数の引数を受け取る関数の組み立て方を身につけます。
その場限りで使う無名関数を、fnと#()の二つの記法で書き分けます。(fn [x] (* x x))と#(* % %)を同じ入力に対して呼び出し、結果が一致することを確かめながら、%・%1・%2・%&による引数アクセスや、#()の可読性の限界(関数を入れ子にできないなど)を理解します。最後はマップで複数の要素にまとめて処理を適用する例を両方の記法で書き、状況に応じた選択感覚を養います。
Clojureの関数が、引数の数(アリティ)ごとに異なる本体を持てる強力な仕組みを学びます。引数0個・1個・2個で挨拶を変えるgreet関数を定義し、それぞれの呼び出し結果を確認したうえで、& argsによる可変長引数で任意個の数を合計する関数も実装します。アリティでデフォルト値を表現する書き方や、固定引数と可変長引数を組み合わせる関数を書き、アリティの分岐とデフォルト引数の自然な表現を体得します。
関数が第一級の値であるという事実を、関数を引数として渡す形で実体験します。apply-twiceのような関数を自分で定義し、incや無名関数を渡して挙動を確かめ、map・filterに無名関数を渡す典型例にも触れます。関数を組み合わせて段階的に値を変換する演習で、関数を値として扱う感覚を定着させます。
関数内で一時的な名前を作るletを使いこなします。底辺と高さから面積を求める例、一度計算した値を使い回す例を動かしながら、letが束縛を順に行えること、内側の式から外側の束縛が見えること、スコープ外では参照できないことを確認します。最後は複数の中間値をletで束縛して威力を計算する関数を読みやすく書き、可読性向上の手段としてletを身につけます。
Clojureを採用するときの利点と欠点を、忖度なくSWOT分析として見渡します。採用すれば確実に得られるものと並べて、導入時の現実的なハードル、導入前に確認すべき優先課題、そして採用判断で意識すべきリスクも率直に把握できます。SWOT形式で整理されているため、チーム導入や個人学習の意思決定にそのまま使えます。
Clojureで最もよく使う順序付きコレクション、ベクタを扱います。[1 2 3]のような角括弧の構文と、conj・assoc・get・nth・countによる基本操作を順に動かしながら、ベクタが末尾追加に最適化されていること、不変ゆえにconjが新しいベクタを返すことを確認します。ログを段階的に組み立てていく演習で、不変データ構造の更新パターンを体得します。
Clojureに残るLisp由来のリスト型を学びます。'(1 2 3)・(list 1 2 3)・conjによる先頭追加を動かし、ベクタとの違い(先頭追加は高速・末尾追加は遅い・nthのコストが線形)を実行例で対比します。コードそのものがリスト構造で表現されるというClojureの根本的性質(同図像性)にも触れ、リストへの先頭追加とベクタへの末尾追加を見比べて用途に応じた選択感覚を養います。
Clojureのプログラムで主役級の役割を担うマップ型を扱います。{:name "..." :hp 120}のようなリテラルと、assoc・dissoc・get・update・merge・contains?を順に呼び出して動作を確認し、キーワードを関数として使う(:name person)という独特の構文も体験します。自分だけのプロフィールマップを作り、フィールドの追加・更新・削除を一連で行う演習で、Clojureのデータ中心設計の核を掴みます。
#{1 2 3}という集合リテラルと、clojure.set名前空間の主要な関数を扱います。contains?・conj・disj・union・intersection・differenceを順に動かし、数学的な集合演算がClojureで自然に書けることを確かめ、集合自身を関数として使う呼び出しも学びます。二つの履修者集合から、両方を取っている人・どちらかだけを取っている人を求める演習に取り組みます。
Clojure全体を統一しているコア概念「シーケンス抽象」を体感します。ベクタ・リスト・マップ・文字列・集合に同じseq・first・rest・next・consを適用し、すべてが同じインターフェースに従う様子を出力で目にします。マップへのseqがエントリの列を、文字列へのseqが文字の列を返すことを確認し、異なる型を集めたコレクションに同じ関数を適用して、抽象の威力を実感します。
現実のアプリでよく現れる入れ子マップへの、安全で簡潔なアクセス方法を学びます。ステータスや装備が深く入れ子になったデータを作り、get-inで深い値を取り出し、assoc-inで深い更新を行い、update-inで関数を適用しながら更新します。パス指定にベクタを使うClojureらしいスタイルを確認したうえで、注文データを模した入れ子マップで値の取り出し・更新・追加を実行します。
Clojureが現実世界でどれほど使われているかを、統計とケーススタディで確かめます。業界別の主要採用企業を整理し、State of Clojure調査から利用者層の安定や用途の分布、そして満足度の異常な高さを読み解きます。TechEmpowerに見るスループットの位置取りや、コミュニティ健全性の主要指標まで含め、言語の健康状態を多角的に評価できます。
Clojureの関数型プログラミングを支える三つのコア関数、map・filter・reduceを一気に習得します。数値ベクタにincをmapし、しきい値で要素をfilterし、+でreduceして総和を求めるパイプラインを動かしながら、中間結果を一行ずつ見て、それぞれの関数がコレクションをどう変形・絞り込み・畳み込むかを追います。最後は「リストから一定年齢以上の名前だけを取り出して集計する」処理を、三つの関数を組み合わせて書きます。
関数呼び出しの入れ子を読みやすく書き直す、スレッディングマクロを学びます。->が値を第一引数として、->>が最後の引数として次の関数に渡す違いを、同じ計算を二通りで書いて出力で体感し、as->・some->・cond->といった派生形にも触れます。文字列のリストを整形してキーワードに変換する一連の処理をスレッディングマクロで書き、データ変換パイプラインの自然な表現を身につけます。
関数そのものを合成・部分適用・並列適用する、comp・partial・juxtを扱います。(comp inc inc inc)・(partial + 100)・(juxt min max count)を順に評価し、それぞれが新しい関数を返すことを確認したうえで、compの順序に気をつけながら、これらを組み合わせて「文字列を整数に変換し10倍する」関数を一行で作ります。数値ベクタに対して最小・最大・件数を一度に求める演習で、関数を素材として組み立てる感覚を養います。
Clojureの遅延評価の力を体感します。(iterate inc 1)で無限の自然数列を作りtakeで先頭10個を取り出す例、(repeatedly #(rand-int 100))で無限の乱数列から必要な数だけ取る例を動かし、lazy-seqで自前のフィボナッチ無限列を定義しながら、必要なものだけが計算される挙動を出力で目にします。最後は無限列とfilterを組み合わせて素数を取り出す演習に取り組みます。
同じ結果を出すreduceとtransduceの、性能と表現力の違いを実コードで比較します。100万件のベクタに対して(->> coll (map inc) (filter odd?) (reduce +))と、トランスデューサ版(transduce (comp (map inc) (filter odd?)) + coll)を実行し、中間コレクションが生成されるかどうかをtimeで計測して、トランスデューサが大きなデータで効くことを体感します。三段階の変換を含むパイプラインをトランスデューサで書き直します。
大規模な反復処理で安全に再帰を行うための仕組みを掘り下げます。loop/recurによる末尾再帰最適化に加え、defn本体で直接recurを呼ぶ書き方や、多変数loop/recurを実例で扱います。相互再帰の場面で必要となるtrampolineで、互いに呼び合う関数を定義し、巨大な引数でもスタックを消費しないことを確認します。階乗やフィボナッチ、100万回規模の反復をloop/recurとtrampolineの両方で書き、再帰の手綱の握り方を身につけます。
Clojureの不変コレクションが、なぜO(log32 n)で更新できるのかを内部実装の視点から理解します。ハッシュ配列マッピング・トライ(HAMT)、ビットマップによる疎なノード表現、構造共有の仕組みを、コードを使わず段階的な図解で追います。なぜ「不変なのに高速」が成立するのか、可変構造との実装比較やアイデアの伝播史まで、腹落ちするレベルで噛み砕いて解説します。
複数のスレッドから同時に更新されても破綻しない可変状態を、Atomで扱います。(atom 0)でカウンタを作り、swap!・reset!・compare-and-set!で更新する例を動かしながら、@や(deref)で値を読み出すこと、swap!が衝突時に自動で再試行することを確認します。swap!に渡す関数を純粋に保つ理由を押さえ、複数の関数から共有マップを更新する状態管理パターンを書き、Clojureらしい「状態の局所化」を体に染み込ませます。
JVMのスレッドを直接扱って計算を並列化する基本道具を学びます。futureで重い計算をバックグラウンドに投げ@で結果を待つ例、promiseでスレッド間の値の受け渡しを行う例、pmapで並列マップを実行する例を順に動かし、timeでシーケンシャル版との実行時間差を確認します。pmapが万能ではないことにも触れ、複数の領域から結果を並列に取得するシミュレーションを書いて、並列化が効くケースの感覚を養います。
Go言語にインスパイアされたcore.asyncで、チャネルとgoブロックを使った並行プログラミングを体験します。(chan)でチャネルを作り、goブロックの中で>!と<!でメッセージを送受信する基本パターンを動かし、close!で終わりを伝える方法や、複数のgoブロックが協調してパイプラインを形成する例、alts!で複数チャネルから最初に来たものを選ぶ例を確認します。生産者と消費者を分離するパターンに取り組みます。
Clojure最大の武器の一つであるマクロを、安全な範囲で学びます。defmacroで自前のunlessマクロを定義し、(unless cond body)が(if test nil body)に展開される様子をmacroexpandで確認しながら、バッククォート(`)・チルダ(~)・~@といったクオート構文の役割を短い例で押さえます。マクロが普通の関数では作れない制御構造を生み出せる理由を実感し、本体を複数式持てるマクロを自分で定義します。
OOP的な継承を使わずに多態を実現する、Clojureの三つの仕組みを比較します。defprotocolとdefrecordで「面積を求める」プロトコルを定義し円と長方形のレコードを実装する例、defmultiとdefmethodでdispatch値ごとに処理を分ける例を動かしながら、両者の性能・拡張性・表現力の違いを整理します。支払い手段ごとに異なる処理を、プロトコルかmultimethodで実装します。
Clojureらしいエラーハンドリングの中核である、ex-infoとex-dataを学びます。try・catch・finallyの基本に加え、(throw (ex-info "メッセージ" {:code ...}))で構造化された例外を投げる例、catch側で(ex-data e)からマップを取り出して分岐する例を動かします。例外を制御フローに使わないという指針にも触れ、入力検証関数で複数の失敗理由をex-infoでまとめて投げ分けます。
Clojureが提供する並行状態管理プリミティブを、概念マップで整理します。同期/非同期、独立/協調という軸でAtom・Ref・Agentを配置し、それぞれの典型ユースケース・強み・注意点を見比べます。Software Transactional Memory(STM)が「複数の参照を協調して更新する」場面でどう力を発揮するかを、コードなしのトランザクション図で理解し、現場での選択頻度や、Clojureの哲学が並行プログラミングをどう簡素化しているかを掴みます。
map・filter・rangeなどが返す遅延シーケンスが、内部でどう評価され、なぜ32要素単位で「チャンク」評価されるのかを理解します。遅延シーケンスの三段階の状態を概念図でたどり、副作用を持つコードを遅延シーケンスに乗せたときに陥りがちな落とし穴(評価タイミングの予測困難、無限シーケンスの危険、ヘッドを保持してメモリリークするパターン)を整理します。コードは使わず、遅延と非遅延の使い分けという確かなメンタルモデルの構築に集中します。
Clojureに導入されたトランスデューサの設計思想を、コードを使わず概念的に理解します。従来のmap・filter・reduceがコレクション特化だったのに対し、トランスデューサがいかに「入力源」と「出力先」から処理を分離するかをパイプライン図で追います。チャネル・遅延シーケンス・ベクタといった異なる文脈で同じ変換を再利用できる利点、性能上のメリット、そして誕生の経緯から、いつ使い・いつ使わないかという指針まで、段階的に把握できます。
clojure.specとコミュニティ製のMalliが、なぜ静的型ではなく「契約」という形でデータの正しさを表現するのかを理解します。仕様(spec)による値の検証、ジェネレーティブテスト、関数の入力・出力契約、エラーメッセージの改善という四本の柱を、コード例なしのフロー図で押さえます。静的型付け言語との設計判断の違いや、specとMalliの選び分け、契約をどこに配置すべきかといった実務的な指針も得られ、動的型付け文化の中でデータ品質を担保する道筋が見えてきます。
Clojureの開発スタイルを特徴づける「REPL駆動開発(RDD)」を、ワークフローと価値命題の視点から理解します。RDDの基本ループ、従来のサイクルとの違い、生きているプロセスに対して関数を再定義しながら設計を進める手法、そして本番システムへのリモートREPL接続といった応用までを段階的にたどります。なぜClojure開発者の満足度が調査で常に高いのか、そのリッチハッカー文化の背景を、コードを書かずに掴み取り、コース全体を締めくくります。
This course contains the use of artificial intelligence.
ソフトウェア開発の複雑さが爆発的に増大する現代において、Clojureは「シンプルさは美徳である」という強い信念に基づいて設計された数少ない言語の一つです。Rich Hickeyが提唱した不変性とデータ指向の哲学は、Web、データ処理、金融、機械学習基盤など多様な領域で実証され、世界中の企業の重要システムを支えています。JVMという世界最強クラスのランタイムに乗りつつ、Lispの表現力とREPL駆動開発の即応性を兼ね備えたClojureは、関数型プログラミングを「理論」ではなく「日常の道具」として体験させてくれる稀有な選択肢です。本コースは、その思想と実装の両面に深く踏み込みます。
本コースの構成には明確な狙いがあります。コーディングを扱う各セクションはまず、その領域が「なぜそう設計されたのか」を語る短い概念レクチャーで幕を開け、続けてREPLで手を動かすハンズオンのコーディングレクチャーへと進みます。出力・基本データ型から始まり、演算と条件分岐、関数定義、ベクタ・リスト・マップ・集合といったコレクション操作へと、概念と実践を交互に織り交ぜながら基礎を一段ずつ固めていきます。中盤以降は高階関数、map・filter・reduce、スレッディングマクロ、comp/partial/juxtによる関数合成、トランスデューサ、そしてAtom・core.async・マクロ・プロトコルといったClojureならではの上級技法へと、同じリズムで踏み込みます。そしてコースの終盤は、STM・Atom・Ref・Agentの状態モデルの四象限、遅延シーケンスのチャンク評価の仕組み、トランスデューサの設計思想、Spec・Malliによる宣言的データ契約、そしてREPL駆動開発とリッチハッカー文化といった、Clojureを「ただのLisp」以上の存在にしている深い概念レクチャー群でじっくりと締めくくります。
対象は、他言語(Java、Python、JavaScript、Rubyなど)での基本的なプログラミング経験があり、関数型パラダイムやLisp系言語に本気で取り組みたい方です。前提知識として高度な数学やJVMの深い理解は不要ですが、変数・関数・データ構造といった一般的な概念に親しんでいることを想定します。受講後は、Clojureで実用的なスクリプトとアプリケーションを書き、REPLを駆使した対話的開発フローを身につけ、不変データと純粋関数を中心としたコード設計ができるようになります。
本コースの特徴は、構文の表層的な解説に留まらず、なぜClojureがこの設計になったのかという「Why」を一貫して掘り下げる点にあります。永続データ構造の内部からマクロのコード生成まで、抽象の層を一つずつ剥がして見せます。関数型プログラミングに本気で向き合いたいエンジニア、複雑性に疲れたシステム開発者、新しい思考の道具を求める知的好奇心の持ち主に、ぜひ受講していただきたい一本です。今すぐ登録して、Lispの伝統とモダンなJVMエコシステムが交差する地点で、プログラミングの新しい風景を体験してください。