Clojure初学者のための関数型プログラミング入門 - コードの読み方から始める

# Clojure初学者のための関数型プログラミング入門 - コードの読み方から始めよう

この記事では、Clojureのコードがどのように構成されているか、どの部分が関数で、どの部分が引数なのかを詳しく解説します。関数型プログラミングが初めての方でも、コードが読めるようになることを目標にします。

## 1. Clojureの基本構文 - すべては括弧から始まる

### 関数呼び出しの基本ルール

Clojureでは**すべての処理が括弧で囲まれ**、**最初の要素が関数、残りが引数**という規則があります。

```clojure
;; 基本的な構文
(関数名 引数1 引数2 引数3...)

;; 具体例
(+ 1 2 3)
;; ↑ ↑ ↑ ↑
;; │ │ │ └── 引数3（数値の3）
;; │ │ └──── 引数2（数値の2）  
;; │ └────── 引数1（数値の1）
;; └──────── 関数（足し算の+）
;; 結果: 6
```

**重要**: 他の言語と違い、関数名が**最初**に来ます！

| 他の言語 | Clojure |
|----------|---------|
| `add(1, 2, 3)` | `(+ 1 2 3)` |
| `Math.max(5, 10)` | `(max 5 10)` |
| `"hello".length()` | `(count "hello")` |

### 練習: 基本的な関数を読んでみよう

```clojure
;; 例1: 数値の計算
(* 4 5)
;; 読み方: 「*関数に、4と5を引数として渡す」
;; 意味: 4 × 5 = 20

;; 例2: 文字列の長さ
(count "hello")
;; 読み方: 「count関数に、"hello"を引数として渡す」
;; 意味: "hello"の文字数 = 5

;; 例3: 最大値を求める
(max 10 5 8 3)
;; 読み方: 「max関数に、10、5、8、3を引数として渡す」
;; 意味: 最大値 = 10
```

## 2. データ構造の理解 - マップとベクター

### マップ（Map）- キーと値のペア

```clojure
;; マップの定義
{:name "太郎" :age 25}
;; ↑      ↑     ↑   ↑
;; │      │     │   └── 値（数値の25）
;; │      │     └────── キー（:age）
;; │      └──────────── 値（文字列の"太郎"）
;; └─────────────────── キー（:name）
```

**マップの構成要素**:
- `{}` : マップを表す括弧
- `:name`, `:age` : キーワード（必ず`:`で始まる）
- `"太郎"`, `25` : 値

### ベクター（Vector）- 順序のあるリスト

```clojure
;; ベクターの定義
["りんご" "みかん" "バナナ"]
;; ↑       ↑       ↑
;; │       │       └── インデックス2の要素
;; │       └─────────── インデックス1の要素
;; └─────────────────── インデックス0の要素
```

**ベクターの構成要素**:
- `[]` : ベクターを表す括弧
- インデックス : 0から始まる位置番号

## 3. サンプルデータの完全解析

```clojure
(def company {:name "ABC Corp"
              :employees [{:name "taro" :dept :engineering}
                          {:name "花子" :dept :sales}]})
```

### この1行を詳しく分解してみましょう

```clojure
(def company {:name "ABC Corp" :employees [...]})
;; ↑   ↑        ↑
;; │   │        └── 引数2: マップ（会社のデータ）
;; │   └─────────── 引数1: シンボル（変数名）
;; └───────────── 特殊形式: def（変数定義）
```

### シンボル（Symbol）とは何か？

**シンボル**は、Clojureにおける「名前」を表すデータ型です。変数名や関数名として使われます。

```clojure
;; シンボルの例
company    ;; これがシンボル（クォートなし）
my-name    ;; これもシンボル
user-data  ;; これもシンボル

;; シンボル vs 文字列の違い
company    ;; シンボル（変数名として使われる）
"company"  ;; 文字列（ただのテキストデータ）
```

**シンボルの特徴**:
- クォート（`"`）で囲まない
- 変数名や関数名として使用される
- ハイフン（`-`）を含むことができる
- 数字で始めることはできない

### `def`でのシンボルの役割

```clojure
(def company {:name "ABC Corp" :employees [...]})
;; ↑   ↑        ↑
;; │   │        └── 引数2: マップ（会社のデータ）
;; │   └─────────── 引数1: company（シンボル = 変数名）
;; └───────────── 特殊形式: def（変数定義）
```

**重要**: `def`の最初の引数は必ずシンボルでなければならない！

```clojure
;; ✅ 正しい（シンボルを使用）
(def my-data {:x 1})

;; ❌ 間違い（文字列を使用）
(def "my-data" {:x 1})  ;; エラー！

;; ❌ 間違い（数字で始まる）
(def 123data {:x 1})    ;; エラー！
```

### シンボルの命名規則

| 良い例 | 悪い例 | 理由 |
|--------|--------|------|
| `user-name` | `userName` | Clojureはケバブケース推奨 |
| `total-count` | `total_count` | アンダースコアよりハイフン |
| `api-key` | `123key` | 数字で始めてはいけない |
| `is-valid?` | `isValid` | 真偽値には`?`をつける慣習 |

### クォート `'` の詳細解説

#### `'`（クォート）の役割

**クォート** = 「評価を停止する」記号

```clojure
;; 通常（評価される）
company
;; => {:name "ABC Corp", :employees [...]}
;; 意味: companyシンボルから値を取得

;; クォート付き（評価されない）
'company
;; => company
;; 意味: companyシンボル自体を返す（値を取得しない）
```

#### 評価される vs 評価されない

| 書き方 | 動作 | 結果 | 用途 |
|--------|------|------|------|
| `company` | シンボルを評価（値を取得） | `{:name "ABC Corp"...}` | 変数の値を使いたい時 |
| `'company` | シンボルを評価しない | `company` | シンボル自体を扱いたい時 |

#### 具体的な例で理解する

```clojure
;; 変数定義
(def my-name "太郎")

;; パターン1: 評価する（通常の使用）
my-name
;; => "太郎"
;; 動作: my-nameから値"太郎"を取得

;; パターン2: 評価しない（クォート使用）
'my-name  
;; => my-name
;; 動作: シンボルmy-name自体を返す

;; パターン3: quote関数（同じ意味）
(quote my-name)
;; => my-name
;; 動作: 'my-nameと完全に同じ
```

#### リストでのクォートの威力

```clojure
;; 通常のリスト（関数として評価される）
(+ 1 2 3)
;; => 6
;; 動作: +関数を実行

;; クォートしたリスト（データとして扱われる）
'(+ 1 2 3)
;; => (+ 1 2 3)
;; 動作: リスト自体を返す（実行しない）

;; より複雑な例
'(def company {:name "ABC"})
;; => (def company {:name "ABC"})
;; 動作: defを実行せず、リスト自体を返す
```

#### なぜクォートが必要なのか？

**Clojureの評価ルール**:
1. 数値・文字列・キーワード → そのまま
2. シンボル → 値を取得しようとする
3. リスト → 関数として実行しようとする

```clojure
;; 問題例: 存在しない変数
undefined-var
;; => エラー: Unable to resolve symbol: undefined-var

;; 解決: クォートで評価を停止
'undefined-var
;; => undefined-var （エラーにならない）
```

#### 実用的な使用場面

##### 1. メタプログラミング

```clojure
;; マクロでコードを生成する時
(defmacro my-def [name value]
  `(def ~name ~value))  ;; バッククォートとアンクォート

;; 関数名をデータとして扱う
(def function-names ['+ '- '* '/])
```

##### 2. 動的なシンボル操作

```clojure
;; シンボルから文字列に変換
(name 'company)
;; => "company"

;; 文字列からシンボルに変換
(symbol "company")
;; => company

;; シンボルかどうか判定
(symbol? 'company)
;; => true
(symbol? company)
;; => false（値なので）
```

##### 3. データ構造でのシンボル保存

```clojure
;; 関数名のリスト
(def operations ['+ '- '* '/])

;; 変数名のリスト
(def variable-names ['x 'y 'z])

;; 設定データ
(def config {'database-host "localhost"
             'database-port 5432})
```

#### クォートの種類

| 記号 | 名前 | 機能 | 例 |
|------|------|------|-----|
| `'` | クォート | 評価停止 | `'(+ 1 2)` → `(+ 1 2)` |
| `` ` `` | バッククォート | テンプレート | `` `(+ 1 ~x)`` |
| `~` | アンクォート | 評価再開 | `` `(+ 1 ~(+ 2 3))`` |
| `~@` | スプライシング | リスト展開 | `` `(list ~@[1 2 3])`` |

#### デバッグでの活用

```clojure
;; コードをそのまま表示したい時
(println '(-> company :employees second :name))
;; => (-> company :employees second :name)
;; 動作: コード自体を出力（実行結果ではない）

;; 関数定義を確認
(meta #'company)
;; => {:line 1, :column 1, :file "user.clj", :name company, :ns user}
```

#### よくある間違いと対処法

```clojure
;; ❌ 間違い: クォートのつけ忘れ
(def symbols [x y z])
;; エラー: x, y, zの値を取得しようとする

;; ✅ 正しい: シンボル自体を保存
(def symbols ['x 'y 'z])

;; ❌ 間違い: 不要なクォート
(def result '(+ 1 2))
;; => (+ 1 2) （計算されない）

;; ✅ 正しい: 計算したい場合
(def result (+ 1 2))
;; => 3
```

#### マクロでのクォート使用例

```clojure
;; 条件付きデバッグマクロ
(defmacro debug [expr]
  `(let [result# ~expr]
     (println "Debug:" '~expr "=>" result#)
     result#))

;; 使用例
(debug (+ 1 2 3))
;; 出力: Debug: (+ 1 2 3) => 6
;; 戻り値: 6
```

#### まとめ：クォートの使い分け

**いつクォートを使うか**:
1. **シンボル自体を扱いたい時**: `'company`
2. **コードをデータとして扱いたい時**: `'(+ 1 2 3)`
3. **メタプログラミング**: マクロやコード生成
4. **設定やメタデータ**: シンボルをキーとして使用

**覚え方**:
- **クォートなし**: 「この変数の値をください」
- **クォートあり**: 「この名前（シンボル）をそのままください」

**`def`の役割**: 
- 特殊形式: `def`
- 引数1: `company` （シンボル = 変数名）
- 引数2: `{:name "ABC Corp" ...}` （保存する値）
- 意味: 「`company`というシンボル（名前）で、マップデータを保存する」

### シンボルの実際の使用例

```clojure
;; 様々なシンボルの定義
(def user-count 100)           ;; user-countというシンボル
(def is-active? true)          ;; is-active?というシンボル
(def api-endpoint "localhost") ;; api-endpointというシンボル

;; シンボルを使って値を取得
user-count    ;; => 100
is-active?    ;; => true
api-endpoint  ;; => "localhost"

;; 関数定義でもシンボルを使用
(defn calculate-total [items]  ;; calculate-totalというシンボル
  (reduce + items))

;; 関数呼び出し
calculate-total  ;; => #function[...] （関数オブジェクト）
(calculate-total [1 2 3])  ;; => 6 （関数を実行）
```

### シンボル vs その他のデータ型

```clojure
;; シンボル（変数名）
my-var

;; 文字列（テキストデータ）
"my-var"

;; キーワード（マップのキーなどに使用）
:my-var

;; 数値
42

;; 実際の使い分け例
(def user-name "太郎")      ;; user-name: シンボル、"太郎": 文字列
(def user {:name "太郎"})   ;; user: シンボル、:name: キーワード、"太郎": 文字列
```

```clojure
{:name "ABC Corp"
 :employees [{:name "taro" :dept :engineering}
             {:name "花子" :dept :sales}]}
```

**構造の解説**:
```
マップ全体
├── キー: :name
│   └── 値: "ABC Corp" （文字列）
└── キー: :employees
    └── 値: [...] （ベクター）
        ├── インデックス0: {:name "taro" :dept :engineering} （マップ）
        └── インデックス1: {:name "花子" :dept :sales} （マップ）
```

## 4. データアクセスの仕組み

### 基本的なマップアクセス

```clojure
(:name company)
;; ↑     ↑
;; │     └── 引数: company（マップが入った変数）
;; └──────── 関数: :name（キーワード）
```

**重要**: キーワード（`:name`）は**関数として使える**！

```clojure
;; これらは同じ意味
(:name company)
(get company :name)

;; 読み方の比較
;; ↓ 「:name関数に、companyを引数として渡す」
(:name company)
;; ↓ 「get関数に、companyと:nameを引数として渡す」
(get company :name)
```

### なぜキーワードが関数になるの？

Clojureでは、キーワードは「そのキーの値を取得する関数」として動作します。

```clojure
;; キーワード関数の例
(:name {:name "太郎" :age 25})    ;; => "太郎"
(:age {:name "太郎" :age 25})     ;; => 25
(:height {:name "太郎" :age 25})  ;; => nil（存在しないキー）
```

## 5. ベクターアクセス関数の詳細

### `first`, `second`, `last`の仕組み

```clojure
;; サンプルベクター
["A" "B" "C" "D"]

;; first関数の詳細
(first ["A" "B" "C" "D"])
;; ↑     ↑
;; │     └── 引数: ベクター
;; └──────── 関数: first（最初の要素を取得）
;; 結果: "A"

;; second関数の詳細
(second ["A" "B" "C" "D"])
;; ↑      ↑
;; │      └── 引数: ベクター
;; └───────── 関数: second（2番目の要素を取得）
;; 結果: "B"

;; last関数の詳細
(last ["A" "B" "C" "D"])
;; ↑    ↑
;; │    └── 引数: ベクター
;; └─────── 関数: last（最後の要素を取得）
;; 結果: "D"
```

### より詳しいベクターアクセス

```clojure
;; nth関数（n番目の要素を取得）
(nth ["A" "B" "C" "D"] 2)
;; ↑   ↑                ↑
;; │   │                └── 引数2: インデックス（2番目）
;; │   └─────────────────── 引数1: ベクター
;; └─────────────────────── 関数: nth
;; 結果: "C"（0から数えて2番目）

;; get関数（安全なアクセス）
(get ["A" "B" "C" "D"] 10)
;; ↑   ↑                ↑
;; │   │                └── 引数2: インデックス（存在しない）
;; │   └─────────────────── 引数1: ベクター
;; └─────────────────────── 関数: get
;; 結果: nil（エラーにならない）
```

## 6. スレッディングマクロ`->`の完全解説

### 従来の書き方の問題点

```clojure
;; 2番目の従業員の名前を取得したい
;; 従来の書き方（右から左に読む必要がある）
(:name (second (:employees company)))
;; ↑      ↑       ↑
;; │      │       └── 3番目: :employees関数でcompanyから従業員リストを取得
;; │      └─────────── 2番目: second関数で2番目の要素を取得
;; └────────────────── 1番目: :name関数で名前を取得
```

**読み方が不自然**: 実際の処理順序と逆順で書かれている！

### `->`マクロの革命

```clojure
;; スレッディングマクロ（左から右に読める）
(-> company :employees second :name)
;; ↑  ↑       ↑          ↑      ↑
;; │  │       │          │      └── 4番目: :name関数で名前を取得
;; │  │       │          └─────── 3番目: second関数で2番目の要素を取得
;; │  │       └────────────────── 2番目: :employees関数で従業員リストを取得
;; │  └────────────────────────── 1番目: company（開始データ）
;; └───────────────────────────── マクロ: ->（スレッディング）
```

**読み方**: 「companyから始めて、employeesを取得し、その2番目を取得し、その名前を取得する」

### `->`マクロの展開過程

`->`マクロは、実際には以下のように段階的に変換されます：

```clojure
;; 元のコード
(-> company :employees second :name)

;; ステップ1: companyを:employeesの引数にする
(-> (:employees company) second :name)

;; ステップ2: (:employees company)をsecondの引数にする
(-> (second (:employees company)) :name)

;; ステップ3: (second (:employees company))を:nameの引数にする
(:name (second (:employees company)))
```

**結果**: 最終的に従来の書き方と同じになる！

## 7. 実際の実行過程を追ってみよう

### データの準備

```clojure
;; まずデータを定義
(def company {:name "ABC Corp"
              :employees [{:name "taro" :dept :engineering}
                          {:name "花子" :dept :sales}]})
```

### ステップバイステップ実行

```clojure
;; ステップ1: 元データ
company
;; => {:name "ABC Corp", :employees [{:name "taro", :dept :engineering} {:name "花子", :dept :sales}]}

;; ステップ2: :employees関数を適用
(:employees company)
;; ↑          ↑
;; │          └── 引数: company（マップ）
;; └───────────── 関数: :employees（キーワード）
;; => [{:name "taro", :dept :engineering} {:name "花子", :dept :sales}]

;; ステップ3: second関数を適用
(second [{:name "taro", :dept :engineering} {:name "花子", :dept :sales}])
;; ↑      ↑
;; │      └── 引数: ベクター（従業員リスト）
;; └───────── 関数: second
;; => {:name "花子", :dept :sales}

;; ステップ4: :name関数を適用
(:name {:name "花子", :dept :sales})
;; ↑     ↑
;; │     └── 引数: マップ（花子のデータ）
;; └──────── 関数: :name（キーワード）
;; => "花子"
```

### `->`を使った場合の実行

```clojure
;; 一度に実行
(-> company :employees second :name)
;; => "花子"

;; 途中経過も確認できる
(-> company :employees)                    ;; => [{...} {...}]
(-> company :employees second)             ;; => {:name "花子", :dept :sales}
(-> company :employees second :name)       ;; => "花子"
```

## 8. より複雑な例で理解を深める

### 詳細なデータ構造

```Clojure
(def detailed-company 
  {:name "ABC Corp"
   :founded 2020
   :employees [{:name "taro" 
                :dept :engineering 
                :skills ["Java" "Clojure"]
                :contact {:email "taro@abc.com" :phone "090-1234-5678"}}
               {:name "花子" 
                :dept :sales 
                :skills ["営業" "マーケティング"]
                :contact {:email "hanako@abc.com" :phone "090-8765-4321"}}]})
```

### 深いネストへのアクセス解析

```clojure
;; 最初の従業員のメールアドレスを取得
(-> detailed-company :employees first :contact :email)

;; 完全分解
;; ステップ1
detailed-company
;; => {:name "ABC Corp", :founded 2020, :employees [...]}

;; ステップ2: :employees関数適用
(-> detailed-company :employees)
;; 内部的には (:employees detailed-company) と同じ
;; => [{:name "taro", :dept :engineering, ...} {...}]

;; ステップ3: first関数適用
(-> detailed-company :employees first)
;; 内部的には (first (:employees detailed-company)) と同じ
;; => {:name "taro", :dept :engineering, :skills [...], :contact {...}}

;; ステップ4: :contact関数適用
(-> detailed-company :employees first :contact)
;; 内部的には (:contact (first (:employees detailed-company))) と同じ
;; => {:email "taro@abc.com", :phone "090-1234-5678"}

;; ステップ5: :email関数適用
(-> detailed-company :employees first :contact :email)
;; 内部的には (:email (:contact (first (:employees detailed-company)))) と同じ
;; => "taro@abc.com"
```

## 9. 関数の引数が複数ある場合

### `nth`関数を`->`で使う

```clojure
;; 3番目の従業員を取得したい場合
;; 従来の書き方
(nth (:employees company) 2)
;; ↑   ↑                  ↑
;; │   │                  └── 引数2: インデックス
;; │   └───────────────────── 引数1: ベクター
;; └─────────────────────── 関数: nth

;; ->を使った書き方
(-> company :employees (nth 2))
;; ↑          ↑         ↑    ↑
;; │          │         │    └── 引数2: インデックス
;; │          │         └─────── 関数: nth
;; │          └─────────────── 1番目の処理: :employees
;; └────────────────────────── データの出発点: company
```

**重要**: 引数が複数ある関数は括弧で囲む！

### 括弧の使い分け

```clojure
;; 引数が1つの場合（括弧不要）
(-> data :key func)

;; 引数が複数の場合（括弧必要）
(-> data :key (func arg1 arg2))

;; 具体例
(-> company :employees (nth 1))              ;; nth関数は引数2つ
(-> company :employees (get 1))              ;; get関数は引数2つ  
(-> company :employees count)                ;; count関数は引数1つ
(-> company :employees (take 2))             ;; take関数は引数2つ
```

## 補足: `def`の正体と役割

### `def`は関数ではなく「特殊形式（Special Form）」

```clojure
(def company {:name "ABC Corp" :employees [...]})
;; ↑   ↑       ↑
;; │   │       └── 引数2: 保存する値
;; │   └─────────── 引数1: 変数名（シンボル）
;; └───────────── 特殊形式: def
```

**重要**: `def`は関数ではありません！**特殊形式（Special Form）**と呼ばれる、Clojureの基本的な構文要素です。

### 関数 vs 特殊形式の違い

| 種類 | 評価のタイミング | 例 |
|------|------------------|-----|
| **関数** | 引数を先に評価してから関数を実行 | `(+ 1 2)` → まず1と2を評価 → +を実行 |
| **特殊形式** | 引数を評価せずに直接処理 | `(def x 10)` → xを評価せず、そのまま変数名として使用 |

### `def`の具体的な動作

```clojure
;; defの基本構文
(def 変数名 値)

;; 具体例1: 数値の保存
(def my-number 42)
;; 動作: 「my-number」という名前で「42」という値を保存

;; 具体例2: 文字列の保存
(def my-name "太郎")
;; 動作: 「my-name」という名前で「"太郎"」という文字列を保存

;; 具体例3: マップの保存
(def person {:name "花子" :age 30})
;; 動作: 「person」という名前で「{:name "花子" :age 30}」というマップを保存
```

### なぜ`def`は特殊形式なのか？

```clojure
;; もしdefが普通の関数だったら...（これは実際には動かない例）
(def company {:name "ABC"})

;; 普通の関数なら、引数が先に評価される
;; 1. company → "companyという変数の値を取得しようとする" → エラー！
;; 2. {:name "ABC"} → マップを評価
;; 3. def関数を実行

;; でも実際のdefは特殊形式なので
;; 1. companyを「変数名」として認識（評価しない）
;; 2. {:name "ABC"}を評価
;; 3. companyという名前で値を保存
```

### Clojureの特殊形式一覧

Clojureには`def`以外にも特殊形式があります：

| 特殊形式 | 役割 | 例 |
|----------|------|-----|
| `def` | 変数定義 | `(def x 10)` |
| `if` | 条件分岐 | `(if true "yes" "no")` |
| `let` | ローカル変数 | `(let [x 5] (+ x 2))` |
| `fn` | 関数定義 | `(fn [x] (* x 2))` |
| `quote` | 評価停止 | `(quote (+ 1 2))` → `(+ 1 2)` |

### `def`の実際の動作を確認

```clojure
;; ステップ1: 変数定義前
company
;; => エラー: Unable to resolve symbol: company

;; ステップ2: defで変数を定義
(def company {:name "ABC Corp"})
;; => #'user/company （変数が作成されたことを示す）

;; ステップ3: 変数定義後
company
;; => {:name "ABC Corp"} （値が取得できる）

;; ステップ4: 変数の存在確認
(bound? #'company)
;; => true （companyという変数が存在する）
```

### `def`と関数の組み合わせ

```clojure
;; 関数の結果をdefで保存
(def sum-result (+ 1 2 3))
;; 動作:
;; 1. (+ 1 2 3) を評価 → 6
;; 2. sum-resultという名前で6を保存

;; 確認
sum-result
;; => 6

;; 他の例
(def employee-count (count (:employees company)))
;; 動作:
;; 1. (:employees company) を評価 → ベクター
;; 2. (count ベクター) を評価 → 数値
;; 3. employee-countという名前で数値を保存
```

### `defn`の正体

実は`defn`（関数定義）も`def`を使って作られています！

```clojure
;; この書き方
(defn greet [name]
  (str "こんにちは、" name "さん！"))

;; は実際にはこれと同じ
(def greet 
  (fn [name]
    (str "こんにちは、" name "さん！")))

;; つまり
;; defn = def + fn の組み合わせ
```

### メモリでの動作イメージ

```clojure
;; defが実行されるとメモリ上で...

(def company {:name "ABC Corp"})
;; メモリ上:
;; company → {:name "ABC Corp"}

(def person {:name "太郎"})
;; メモリ上:
;; company → {:name "ABC Corp"}
;; person  → {:name "太郎"}

;; 変数を使用すると
(:name company)
;; 動作:
;; 1. companyという名前からメモリ上の値を取得
;; 2. {:name "ABC Corp"} を取得
;; 3. :name関数で "ABC Corp" を取得
```

### `def`使用時の注意点

```clojure
;; ❌ 同じ名前で再定義（混乱の原因）
(def x 10)
(def x 20)
x ;; => 20 （前の値は消える）

;; ❌ letの中でdef（推奨されない）
(let [y 5]
  (def z y))  ;; グローバル変数になってしまう

;; ✅ 適切な使い方
(def config {:db-host "localhost" :db-port 5432})
(def users [{:name "太郎"} {:name "花子"}])
```

### まとめ：`def`の特徴

1. **特殊形式**: 関数ではなく、Clojureの基本構文
2. **変数作成**: グローバルな変数を作成する
3. **評価制御**: 最初の引数（変数名）は評価しない
4. **永続的**: 一度定義すると、そのREPLセッション中はずっと使える
5. **上書き可能**: 同じ名前で再定義できる（注意が必要）

**覚え方**: 
- `def` = 「このデータに名前をつけて保存する」命令
- 関数 = 「データを受け取って何かを返す」処理