Upgrade to Pro — share decks privately, control downloads, hide ads and more …

"Simple Made Easy" Made Easier: Clojureに学ぶsimpl...

"Simple Made Easy" Made Easier: Clojureに学ぶsimplicity

Rich Hickeyの有名なプレゼン"Simple Made Easy"をより踏み込んで解説します。
cf. 2019年版: https://speakerdeck.com/lagenorhynque/simple-made-easy-made-easy

Avatar for Kent OHASHI

Kent OHASHI

May 28, 2026

More Decks by Kent OHASHI

Other Decks in Programming

Transcript

  1. 関数型プログラミング( 言語) の愛好者/ 実践者 特に , , がエレガントで好き の運営スタッフ( 座長のひとり)

    主に(CfP を含む) メインコンテンツの準備を担当 のシニアエンジニア スタートアップと投資家のやり取りを効率化する データ管理プラットフォームを開発 ソフトウェア設計/ 開発とともに会計/ 財務/ 法務 について探求するのも好き lagénorhynque 🐬カマイルカ Clojure Haskell Flix 関数型まつり2026 株式会社スマートラウンド 2
  2. [PR] 2026 年7 月の で登壇予定🐬 関数型まつり2026 速習FP in Scala with

    Flix: Flix 言語で親しむ純粋関数型のコード設計 3
  3. (2019 年7 月) での発表 Fun Fun Functional (2) 関数型言語 Lightning

    Talks!! "Simple Made Easy" Made Easy: Clojure の設計思想を理解しよう [ 書き起こし記事] "simple" と"easy" はどう違う? Simple Made Easy を解説 Part1 5
  4. 今回のテーマ (-> (simple-made-easy-made-easy) revisit ; 「"Simple Made Easy" Made Easy

    」をおさらい deepen ; 近年のClojure エコシステム/ コミュニティの進化を深掘り extend) ; Clojure の範囲に留まらないより一般的な示唆へと展開 6
  5. 1. simple と easy という言葉 2. "Simple Made Easy" とは

    3. simple と easy の意味 4. simple と easy の関係 5. なぜ simplicity を重視するのか 6. どのように simple にするのか 7. Clojure に見る simplicity 8. simple と easy の区別のより抽象的( メタ) な示唆 7
  6. Clojure コミュニティにおける simple 明確に定義された特別な意味がある easy と混同されやすいが概念的にまったく違う Clojure とは simple さ(simplicity)

    を追求した言語 あらゆる場面で非常に重視されている概念 設計の良し悪しを図る指標のひとつ 9
  7. (at 2011) Clojure 作者Rich Hickey による極めて有名な発表 コミュニティで simple の概念が浸透するきっかけ 日本ではタイトルも趣旨も(

    特にClojurian 以外から) わりと誤解されているかも cf. (at 2012) Simple Made Easy Strange Loop Simplicity Matters RailsConf シンプルさの必要性 · eed3si9n 11
  8. タイトル"Simple Made Easy" の意味 敢えて訳せば「simple 簡単解説」 例えば という本がある 英語の文法的には: X

    makes Y easy. → Y is made easy [by X]. → Y made easy [by X] ( 簡単になったY) 本題の simple と easy を掛けた言葉遊びでもある simple を追求すると easy にもなる? 英語的にも内容的にもちょっと苦しい解釈 Word Power Made Easy 12
  9. simple の意味 < simplex (= sim- + plex) ラテン語 simplex

    原義: 「一折り」 「一編み」 「一捻り」 「単一の役割」 「単一の責務」 「単一の概念」 「単 一の次元」 ※ 「単一の実体/ 操作」 ではない 客観的な概念: 設計対象の構造の単純さ 対義語: (= com- + plex) 原義: 「絡まり合った」 「折り重なった」 「もつれ た」 simple complex 14
  10. easy の意味 (= + -y) < aise/eise < adjacens ラテン語

    adjacens (cf. 🇬🇧 adjacent) 原義: 「近くにある」 「隣接した」 「身近な」( 物理的に近い) 「親しみがある」( 自分 の理解に近い) 「易しい」( できることに近い) 主観的/ 相対的な概念: 利用者からの( 広義の) 近さ 対義語: 原義: 「強い」 「手ごわい」 ※ easy とは無関係 easy ease hard 15
  11. simple と easy の二者択一ではない simple/complex, easy/hard の直交した2 つの評価軸 単純なトレードオフの関係にはない simple

    AND easy も complex AND hard もある 「 easy よりも simple を選ぼう」 ではない complex になりうるものを避けて simple を追求 しようというのがRich Hickey の主張 選択するのは simple OR complex であって simple OR easy ではない simple AND easy は十分に実現可能 17
  12. 構図例: "easy but complex" vs "simple but hard" ease を優先し

    complexity ( ↔ simplicity) を甘受する 短期: easy なため生産性が高く、 complex である ことも直ちに支障をきたさない 中長期: complex ゆえに生産性が急速に低下 構造的な限界により徐々に手に負えなくなる ⭐️ simplicity を優先し hardness ( ↔ ease) を甘受する 短期: hard ゆえに生産性が低く、 simple なもの を課題に適用するにはいくらか時間が掛かる 中長期: simple なため生産性が高い水準を維持 hard から easy へと習熟/ 環境整備も進む 18
  13. よくある誤解/ 派生解釈と🐬の見解(1) 「 simple 簡単解説」というのが文字通りの解釈 simple と easy の峻別という本題に関わる最重要の キーワードが見事に組み込まれた表現

    しかし、タイトル自体に何かを促すメッセージ性が あるとは読み取りがたい "Simple Made Easy" というRich Hickey による標語がある 19
  14. よくある誤解/ 派生解釈と🐬の見解(2) simplicity と ease がもたらしうる実用的メリットを 分かりやすく伝えようという試みに感じられる しかし、 simplicity が客観的な構造の問題から主観

    的な体験の問題に変質してしまう危うさがある 「覚えることが少ない」という体験はむしろ easy であることの例と位置付けるのが素直そう simple: 覚えることの少なさ重視 easy: 手数の少なさ重視 20
  15. よくある誤解/ 派生解釈と🐬の見解(3) simple にすると ease が損なわれ、 easy にすると simplicity が損なわれるだろうか?

    確かに、 simple but hard なもの、 easy but complex なものは両極端で分かりやすい対比 しかし、 「設計対象の構造の単純さ」と「利用者 からの( 広義の) 近さ」というまったく異なる性質 の間に不可避的な連動関係があるとは考えがたい simple と easy はトレードオフなので simple を選ぼう 21
  16. 誤解/ 派生解釈例に共通する傾向( 🐬のメタ読み) simplicity を分かりやすく(easy に) 理解しようとす るあまり、 simplicity が何かと

    complect している 例1: ( 例えば) simple にすると easy になるという 論理関係が加わっている 例2: simplicity に主観的な要素が加わっている 例3: simple/complex, easy/hard という独立した 評価軸が単一軸の二項対立にまとまっている 22
  17. simple にするメリット 構造的に( 必然的に) — simplicity の内在的性質 組み合わせやすい(composable) 独立性が高い(modular) 人間的に(

    結果的に) — 派生的な ease への好影響 理解しやすい 変更しやすい デバッグしやすい 柔軟 あとから方針/ 決定を見直すことも容易 置き換えられる 25
  18. simple なものを見極める complexity をもたらす( している) もの を避ける もともと simple なものを利用する

    抽象化する( ) abstract の原義は「引き離す」(draw away) 詳細を覆い隠すことではない who, what, when, where, why, how をそれぞれ 検討することがヒントになるかも あらかじめ問題を simple にする( ) complect abstract simplify 27
  19. すべて丸括弧ではなく複数の括弧を使い分ける 丸括弧が複数の役割を担って complect している as code: オペレーター呼び出し 束縛フォーム cond の節など、特殊形式/

    マクロの要素 as data: コンスセル( によるリスト/alist/plist など) ;; Common Lisp: Clojure 以前からあるLisp の例 (defun fizzbuzz (n) (let ((fizzp (zerop (mod n 3))) (buzzp (zerop (mod n 5)))) (cond ((and fizzp buzzp) "Fizz Buzz") (buzzp "Buzz") (fizzp "Fizz") (t n)))) 29
  20. 括弧を役割ごとに使い分けたほうが simple ( ): オペレーター呼び出し(as code) 、リスト(as data) [ ]:

    束縛フォーム(as code) 、ベクター(as data) { }: メタデータ(as code) 、マップ(as data) ℹ️ Common Lisp でもリーダーマクロによって括弧 の意味付けの変更は可能 ;; Clojure (defn fizzbuzz [n] (let [fizz? (zero? (mod n 3)) buzz? (zero? (mod n 5))] (cond (and fizz? buzz?) "Fizz Buzz" buzz? "Buzz" fizz? "Fizz" :else n))) 30
  21. オブジェクトよりも値 オブジェクト( クラス) に以下が complect している 値(value): それ自体としては不変のデータ [ ミュータブルな場合]

    状態(state): アイデンティ ティに紐付く値が時とともに変化するもの [ メソッドを持つ場合] 関数: オブジェクトの文脈 でのクロージャー 名前空間/ モジュール: 定義を束ねるもの // Scala: オブジェクト指向言語の例 case class Coffee(price: Double): def applyTax(rate: Double): Coffee = copy(price = price * (1 + rate)) 31
  22. Clojure では構造的に分離されていて simple 値(value): ただの不変のデータ [ 状態(state) を扱いたい場合] 次節で紹介 💁‍♂️

    関数: ただのトップレベル関数 名前空間/ モジュール: ns として独立 ℹ️ Scala の により( メソッドとしての) 関数の分離は部分的に可能 ;; Clojure ;; (require '[lagenorhynque.cafe.coffee :as-alias coffee]) (defn make-coffee [price] #::coffee{:price price}) (defn apply-tax [coffee rate] (update coffee ::coffee/price * (+ 1 rate))) 拡張メソッド 32
  23. 変数よりも管理された参照型 ( 可変の) 変数に以下が complect している アイデンティティ: 値が変化しても変わらない同 一の実体 値:

    変数に紐付いているデータ 時間: 再代入のたびに生じるアイデンティティと 値の紐付き関係の遷移 // Scala: ( 可変の) 変数を持つ言語の例 def heavyCalculation(xs: List[Int]): Int = var result = 0 // 変数を宣言/ 初期化 for x <- xs do result += x * x // 変数に再代入 result // 変数を参照 33
  24. 参照型では構造的に分離されていて simple アイデンティティ: 参照型そのもの 値: 参照型が保持するデータ 時間: 更新操作のたびに生じるアイデンティティ と値の関係の遷移 ⚠️

    並行処理向けには atom (CAS), ref (STM), etc. ℹ️ Scala のサードパーティライブラリには Ref など 参照型を提供するものがある ;; Clojure (defn heavy-calculation [xs] (let [result (volatile! 0)] ; 初期値を指定して参照型を導入 (doseq [x xs] (vswap! result + (* x x))) ; 参照型の値を更新( 差し替え) @result)) ; 参照型の値を参照 34
  25. 継承よりもアドホック多相的な仕組み サブタイピング( サブタイプ多相) により、継承関係 にある複数の型/ クラス同士が complect している // Scala:

    ( 継承を備えている) オブジェクト指向言語の例 // インターフェースの定義 trait Shape: def area: Double // クラス( 型) の定義とともにインターフェースの実装 class Rectangle(width: Double, height: Double) extends Shape: def area = width * height class Circle(radius: Double) extends Shape: def area = scala.math.Pi * radius * radius 35
  26. Clojure の ではデータ型定義とインター フェース実装が分離可能で simple への解答例でもある ℹ️ Scala にも というアドホック多相機構が

    ある ;; Clojure ;; インターフェースの定義 (defprotocol Shape (area [this])) ;; データ型の定義 (defrecord Rectangle [width height]) (defrecord Circle [radius]) ;; インターフェースの実装 (extend-protocol Shape Rectangle (area [{:keys [width height]}] (* width height)) Circle (area [{:keys [radius]}] (* Math/PI radius radius))) プロトコル Expression Problem 型クラス 36
  27. パターンマッチングよりもアドホック多相的な仕組み パターンマッチングではパターン(who) と対応する 振る舞い(what) のペアが複数 complect している # Elixir: パターンマッチングを多用する言語の例

    defmodule Geometry do # 関数定義とともに引数でパターンマッチ def area(%{type: :rectangle, width: w, height: h}), do: w * h def area(%{type: :circle, radius: r}), do: :math.pi() * r * r end 37
  28. Clojure の ではディスパッチ関数 (who) とメソッド実装(what) が分かれていて simple ℹ️ Elixir にもClojure

    類似の がある ;; Clojure ;; ディスパッチ関数 (defmulti area :type) ;; ディスパッチする値ごとのメソッド実装 (defmethod area :rectangle [{:keys [width height]}] (* width height)) (defmethod area :circle [{:keys [radius]}] (* Math/PI radius radius)) マルチメソッド プロトコル 38
  29. では軽量スレッドでの振る舞い(what) と 値を送受信するチャネル(who) が分かれていて simple ;; Clojure (require '[clojure.core.async :refer

    [<! >! chan go]]) ;; チャネル/ ブロッキングキュー (def ch (chan)) ;; 軽量スレッドでチャネルへ値を送信 (go (>! ch "hello")) ;; 軽量スレッドでチャネルから値を受信 (go (println (<! ch))) core.async 40
  30. プラグインではなくデータ主体のCLI/ ビルドツール : deps.edn の中身はただのデータ : build.clj の中身はただの関数 cf. :

    project.clj の中身は( マクロを含む) コード Java のMaven の系譜のビルドツール プラグイン拡張モデル 🐬< 設定( データ) とビルドロジック( 関数) が分かれて いて simple Clojure CLI tools.build Leiningen 42
  31. 破壊的変更を避けた積み重ねによる進化 Clojure エコシステム: 言語本体: 2009 年(v1.0) から2026 年(v1.12) 現在に 至るまで破壊的変更のない積み重ね

    標準/ サードパーティライブラリ: 同様の安定進化 cf. Scala エコシステム: 破壊を伴うイノベーション 🐬< simple な構造を吟味しながら組み合わせて破壊 なく進化させていく文化 43
  32. Clojure とScala のコードベースの変遷 (HOPL IV, 2020) で示される、 Clojure とScala のコードベースの進化の違い

    🐬< A History of Clojure Rich Hickey も述べるように良し悪しは一概に 言えないが、コミュニティの価値観が表れている 44
  33. 改めて simple と easy の根本的な違いとは "Simple Made Easy" の核心: simple

    ≠ easy simple である(simplicity) 設計対象の構造の単純さ 客観的な概念 easy である(ease) 利用者からの( 広義の) 近さ 主観的/ 相対的な概念 ⇒ Clojure エコシステム/ コミュニティは simplicity を 追求して長期にわたり安定進化してきた 46
  34. simplicity と ease の対比をさらに抽象化してみると simplicity → 対象/ 客体(object) ・モノの構造 ease

    → 主体(subject) ・ヒトの対象との関わり方 学習/ 経験や環境など、個人/ 社会の対象との向き 合い方 simplicity と ease を区別し simplicity を優先する → モノへの投資とヒトへの投資を区別する ヒトが移り変わっても残るモノには最初に意識的 に投資する 47
  35. 長く残るモノと移り変わるヒトから連想する古い格言 🇬🇧: Art is long, life is short/brief. 🇯🇵: 技芸は長く、人生は短い。

    古希語( 原典): ὁ βίος βραχύς, ἡ δὲ τέχνη μακρή 原文での趣旨: 人生は短いのに対して( 医療) 技術の 道は長い( だから時間を無駄にせず学ばなければ) 。 後世の意味の変化: ( 芸術家の) 人生は短く儚いが、 芸術は長く残る。 ars longa, vita brevis 48
  36. 技芸(ars) を磨きながら人生(vita) を高める多様な道 言語/ エコシステムとコミュニティの選択 Clojure: simplicity を追求しながら ease を高める

    他のLisp (e.g. Common Lisp) 他のJVM 言語(e.g. Scala) 他の関数型言語(e.g. Scala, Elixir) ソフトウェア開発者として、さらには人として いかなる技芸を学び磨き上げ、何を残せるだろう 自分と社会のより良い体験/ 人生に向けて、何が できるだろう 49
  37. user> (-> (simple-made-easy-made-easy) revisit deepen extend) "Simple Made Easy" Made

    Easier ;; simplicity という長く続く価値を、皆さんにとってより身近に 51
  38. Further Reading Simple Made Easy matthiasn/talk-transcripts > Hickey_Rich/SimpleMadeEasy.md Clojure と「Simple

    Made Easy 」 - 紙箱 Simplicity Matters シンプルさの必要性 · eed3si9n A History of Clojure Rich Already Answered That! Clojurian が出会ったsimple 志向なJVM 関数型言語 Flix —— ファーストインプレッション 52