# 機能設計書 11-Enumerableモジュール

## 概要

本ドキュメントは、mrubyにおけるEnumerableモジュールの機能設計を記述する。Enumerableは、コレクションクラスに対して共通の列挙・検索・集約操作を提供するミックスインモジュールである。

### 本機能の処理概要

Enumerableモジュールは、`each`メソッドを提供するクラスにインクルードすることで、`map`、`select`、`reject`、`inject`、`sort`、`min`、`max`等の豊富なイテレーション機能を自動的に利用可能にする。ISO 15.3.2に準拠した実装であり、Array、Hash、Range等のコレクションクラスの基盤となるモジュールである。

**業務上の目的・背景**：コレクション操作は、あらゆるプログラミングにおいて頻繁に行われる基本操作である。各コレクションクラスが個別に列挙メソッドを実装するのではなく、共通のモジュールとして提供することで、コードの重複を排除し、一貫したインターフェースを実現する。mrubyは組み込み環境向けの軽量Ruby実装であるため、最小限のコードで最大限の機能を提供する設計思想とも合致する。

**機能の利用シーン**：配列やハッシュなどのコレクションに対して、要素のフィルタリング、変換、集約、検索、ソートなどの操作を行う場面で利用される。具体的には、データの抽出（select/reject）、データ変換（map/collect）、集計（inject/reduce）、最大・最小値の取得（max/min）などが挙げられる。

**主要な処理内容**：
1. `each`メソッドを基盤とした要素の列挙処理
2. ブロックによるフィルタリング（all?, any?, select, reject, grep, partition）
3. 要素の変換・マッピング（collect/map）
4. 要素の集約・畳み込み（inject/reduce）
5. 最大・最小値の算出（max, min）
6. ソート処理（sort）
7. 要素検索（detect/find, include?/member?）
8. 配列変換（entries/to_a）
9. インデックス付き列挙（each_with_index）
10. ハッシュ値の算出（hash）

**関連システム・外部連携**：Enumerableモジュールは、Array、Hash、Rangeなどの組み込みクラスにインクルードされる。`sort`メソッドは要素の`<=>`演算子に依存し、Comparableモジュールとの連携が前提となる。

**権限による制御**：特になし。全てのオブジェクトからインクルード可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | CLIベースのランタイム機能のため関連画面なし |

## 機能種別

計算処理 / データ操作 / イテレーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| block | Proc | No | 各メソッドに渡すブロック | ブロックなしの場合、一部メソッドはEnumeratorを返す |
| pattern | Object | Yes（grepのみ） | ===演算子でマッチングするパターン | なし |
| obj | Object | Yes（include?のみ） | 検索対象オブジェクト | なし |
| ifnone | Object | No（detectのみ） | 要素が見つからなかった場合のデフォルト値 | callメソッドを持つオブジェクト |
| args | Array | No（injectのみ） | 初期値とシンボル（最大2個） | 3個以上でArgumentError |

### 入力データソース

インクルード先クラスの`each`メソッドが提供する要素列。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 配列 | Array | collect, select, reject, grep, sort, entries, partition の戻り値 |
| 真偽値 | Boolean | all?, any?, include?/member? の戻り値 |
| オブジェクト | Object | detect/find, max, min, inject/reduce の戻り値 |
| self | Object | each_with_index の戻り値 |
| Integer | Integer | hash の戻り値 |

### 出力先

呼び出し元への戻り値として返却。

## 処理フロー

### 処理シーケンス

```
1. Enumerableモジュールの初期化
   └─ mrb_init_enumerable() により Enumerable モジュールを定義
      └─ __update_hash 内部メソッドを登録
2. インクルード先クラスでの利用
   └─ クラスが `include Enumerable` を宣言
3. 各メソッドの呼び出し
   └─ self.each を呼び出して要素を列挙
      └─ ブロックによる要素の処理（フィルタ/変換/集約）
      └─ 結果の返却
```

### フローチャート

```mermaid
flowchart TD
    A[メソッド呼び出し] --> B{ブロックあり?}
    B -->|No| C[to_enum を返す]
    B -->|Yes| D[self.each で要素列挙開始]
    D --> E{次の要素あり?}
    E -->|Yes| F[ブロックに要素を渡す]
    F --> G[結果を蓄積/判定]
    G --> E
    E -->|No| H[最終結果を返す]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-11-01 | eachメソッド必須 | Enumerableをインクルードするクラスはeachメソッドを定義する必要がある | 常時 |
| BR-11-02 | <=>演算子必須 | max, min, sortを使用する場合、要素は<=>演算子を実装する必要がある | max/min/sort使用時 |
| BR-11-03 | ブロックなし時の挙動 | ブロックが渡されない場合、多くのメソッドはEnumeratorオブジェクトを返す | ブロックなし時 |
| BR-11-04 | inject初期値 | injectに初期値が与えられない場合、最初の要素が初期値となる | inject呼び出し時 |
| BR-11-05 | __svalue変換 | 複数値のyieldに対して__svalueで単一値に変換する | 各メソッド内部 |

### 計算ロジック

- **hash計算**: `h = 12347` を初期値とし、各要素について `h = __update_hash(h, i, e.hash)` で更新。`__update_hash`は `hash ^= ((uint32_t)hv << (index % 16))` で計算。
- **inject/reduce**: ブロックを用いた畳み込み演算。Symbolが渡された場合は`__send__`で演算メソッドを呼び出す。

## データベース操作仕様

### 操作別データベース影響一覧

該当なし（インメモリ操作のみ）。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentError | injectに3個以上の引数が渡された場合 | 引数の数を修正する |
| - | NoMethodError | eachメソッドが未定義のクラスでEnumerableメソッドを呼び出した場合 | eachメソッドを実装する |
| - | ArgumentError | max/min/sortで<=>が未定義の要素を比較しようとした場合 | <=>演算子を実装する |

### リトライ仕様

該当なし。

## トランザクション仕様

該当なし（インメモリ操作のみ）。

## パフォーマンス要件

- 全メソッドがeachの線形走査に基づくため、計算量はO(n)（sortはO(n log n)）
- インクリメンタルGCとの連携により、大量要素のイテレーション中もGCが動作可能

## セキュリティ考慮事項

- ブロック内での例外発生時も適切にスタックが巻き戻される
- hash計算で再帰検出機能あり（`__method_recursive?(:hash)`）

## 備考

- ISO 15.3.2に準拠した実装
- CRubyとの互換性を維持しつつ、組み込み環境向けに最適化
- `__svalue`は内部メソッドで、複数値yieldの単一値変換に使用

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

Enumerableモジュールは特別なデータ構造を持たず、インクルード先のeachメソッドに依存する。まずはモジュールの定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | enum.c | `src/enum.c` | C側のモジュール定義と`__update_hash`内部メソッドの実装 |

**読解のコツ**: enum.cは非常に短く、C側ではモジュール定義と内部ハッシュ更新関数のみを提供している。主要ロジックはRuby側（mrblib/enum.rb）に実装されている点に注意。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | enum.c | `src/enum.c` | `mrb_init_enumerable()`関数でモジュール定義 |

**主要処理フロー**:
1. **26-30行目**: `mrb_init_enumerable()`でEnumerableモジュールを定義し、`__update_hash`メソッドを登録

#### Step 3: Rubyレベルのメソッド実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | enum.rb | `mrblib/enum.rb` | 全メソッドのRuby実装（ISO 15.3.2準拠） |

**主要処理フロー**:
- **14-16行目**: モジュール定義とNONE定数
- **26-33行目**: `all?` - 全要素が真かを判定
- **43-50行目**: `any?` - いずれかの要素が真かを判定
- **59-65行目**: `collect`/`map` - 各要素をブロックで変換
- **75-84行目**: `detect`/`find` - 条件に一致する最初の要素を検索
- **93-102行目**: `each_with_index` - インデックス付きイテレーション
- **109-116行目**: `entries`/`to_a` - 配列への変換
- **131-139行目**: `find_all`/`select` - 条件に一致する全要素を抽出
- **149-158行目**: `grep` - パターンマッチによるフィルタリング
- **167-172行目**: `include?`/`member?` - 要素の包含判定
- **182-207行目**: `inject`/`reduce` - 畳み込み演算
- **223-241行目**: `max` - 最大値の取得
- **250-268行目**: `min` - 最小値の取得
- **286-299行目**: `partition` - 条件による二分割
- **308-316行目**: `reject` - 条件に一致しない要素を抽出
- **333-335行目**: `sort` - ソート
- **344-357行目**: `hash` - ハッシュ値計算（再帰検出あり）

### プログラム呼び出し階層図

```
Enumerableメソッド呼び出し
    |
    +-- self.each (インクルード先クラスのeachメソッド)
    |       |
    |       +-- ブロック呼び出し (block.call)
    |              |
    |              +-- val.__svalue (複数値の単一値変換)
    |
    +-- __update_hash (C実装: enum_update_hash)
    |       |
    |       +-- ビット演算によるハッシュ更新
    |
    +-- Array#sort (sortメソッド内部)
            |
            +-- <=> 演算子 (要素比較)
```

### データフロー図

```
[入力]                    [処理]                          [出力]

コレクション要素     each で要素列挙                結果配列/値
(self.each)   -----> ブロックで各要素を処理 -----> Array / Boolean
                     |                             / Object
                     +-- フィルタ系: 条件判定
                     +-- 変換系: ブロック適用
                     +-- 集約系: 累積演算
                     +-- 検索系: 条件マッチ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| enum.c | `src/enum.c` | ソース（C） | モジュール定義と__update_hash実装 |
| enum.rb | `mrblib/enum.rb` | ソース（Ruby） | 全Enumerableメソッドの実装 |
| proc.h | `include/mruby/proc.h` | ヘッダ | Procオブジェクト（ブロック）の構造定義 |
| presym.h | `include/mruby/presym.h` | ヘッダ | プリコンパイルシンボル定義 |
