# 機能設計書 41-sequtils

## 概要

本ドキュメントは、Nim標準ライブラリの`sequtils`モジュールの機能設計について記述する。`sequtils`は、シーケンス（seq）、文字列（string）、配列（array）に対する関数型プログラミングスタイルの操作を提供する汎用ユーティリティモジュールである。

### 本機能の処理概要

**業務上の目的・背景**：`sequtils`モジュールは、Nimプログラムにおけるコレクション操作を簡潔かつ宣言的に記述するために設計されている。`system`モジュールが提供する基本的な操作（`newSeq`, `@`, `add`, `&`, `in`等）を拡張し、関数型プログラミング言語から着想を得た高階関数やテンプレートを提供することで、開発者の生産性向上とコードの可読性向上を実現する。

**機能の利用シーン**：
- データ変換処理（map/mapIt）：APIレスポンスの加工、型変換、フォーマット変更
- データフィルタリング（filter/filterIt）：条件に合致するデータの抽出
- 集約処理（foldl/foldr）：合計値計算、文字列連結、リダクション操作
- 検証処理（all/any）：全要素・一部要素の条件チェック
- データ結合・分割（zip/unzip, concat/distribute）：複数コレクションの操作
- 重複排除（deduplicate）：ユニーク値の抽出
- インデックス検索（minIndex/maxIndex/findIt）：最小・最大値位置の特定

**主要な処理内容**：
1. 変換系処理（map, mapIt, apply, applyIt）：各要素に関数を適用し、新規シーケンス生成または既存シーケンスの変更
2. フィルタリング系処理（filter, filterIt, keepIf, keepItIf）：条件に基づく要素の選択・除外
3. 畳み込み処理（foldl, foldr）：要素の左/右からの累積演算
4. 検査系処理（all, allIt, any, anyIt, count, countIt）：条件チェックとカウント
5. 結合・分割系処理（concat, zip, unzip, distribute）：コレクションの統合・分離
6. シーケンス生成（toSeq, cycle, repeat, newSeqWith）：新規シーケンスの作成
7. 要素操作（insert, delete, deduplicate, addUnique）：要素の追加・削除・重複排除
8. 統計系処理（min, max, minIndex, maxIndex, minmax）：最小・最大値の取得

**関連システム・外部連携**：本モジュールは純粋なユーティリティライブラリであり、外部システムとの直接連携はない。`std/sugar`モジュールの`collect`マクロや`=>`演算子と組み合わせて使用されることが多い。

**権限による制御**：該当なし（ライブラリモジュールのため）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本モジュールはCLIライブラリのため画面関連なし |

## 機能種別

ユーティリティライブラリ / コレクション操作 / 関数型プログラミング支援

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| s / sequence | openArray[T] / seq[T] | Yes | 操作対象のシーケンス・配列・文字列 | - |
| pred / op | proc(x: T): bool / proc(x: T): S | 関数による | 各要素に適用する述語または変換関数 | - |
| it式 | untyped | テンプレートによる | `it`変数を使用した式（mapIt, filterIt等） | - |

### 入力データソース

- プログラム内のシーケンス（seq）
- 配列（array）
- 文字列（string）
- イテレータ（toSeq使用時）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | seq[T] / seq[S] | 変換・フィルタ後の新規シーケンス |
| result | T | 畳み込み結果（foldl/foldr） |
| result | bool | 条件チェック結果（all/any） |
| result | int | カウント結果・インデックス（count/minIndex/maxIndex） |
| result | (T, T) | 最小・最大ペア（minmax） |

### 出力先

呼び出し元プログラムへの戻り値として返却

## 処理フロー

### 処理シーケンス

```
1. map/mapIt処理
   └─ 入力シーケンスの各要素に変換関数を適用し、結果を新規シーケンスに格納

2. filter/filterIt処理
   └─ 入力シーケンスの各要素に対し述語を評価し、trueの要素のみ新規シーケンスに追加

3. foldl処理
   └─ 先頭要素を初期値とし、左から右へ累積演算を実行

4. foldr処理
   └─ 末尾要素を初期値とし、右から左へ累積演算を実行

5. toSeq処理
   └─ イテレータ/イテラブルをシーケンスに変換
```

### フローチャート

```mermaid
flowchart TD
    A[入力: シーケンス/配列/文字列] --> B{操作種別}
    B -->|変換| C[map/mapIt]
    B -->|フィルタ| D[filter/filterIt]
    B -->|畳み込み| E[foldl/foldr]
    B -->|検査| F[all/any]
    B -->|生成| G[toSeq/cycle/repeat]
    C --> H[新規シーケンス生成]
    D --> H
    E --> I[単一値返却]
    F --> J[bool値返却]
    G --> H
    H --> K[結果シーケンス]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 空シーケンス許容 | filter/map等は空シーケンスを入力として許容し、空シーケンスを返却 | 常時 |
| BR-02 | foldl/foldr最小要素数 | foldl/foldrは最低1要素を必要とし、空シーケンスでassertエラー | 空シーケンス入力時 |
| BR-03 | 短いシーケンスでのzip | zip操作は短い方のシーケンス長に合わせて結果を生成 | 異なる長さのシーケンス入力時 |
| BR-04 | isSortedフラグ | deduplicate関数のisSorted=trueは高速アルゴリズムを使用 | ソート済みシーケンス入力時 |

### 計算ロジック

- **foldl**: `result = op(op(op(a[0], a[1]), a[2]), ...)`
- **foldr**: `result = op(a[0], op(a[1], op(a[2], ...)))`
- **distribute**: シーケンスをnum個のサブシーケンスに分割。spread=trueで均等分配、falseで前詰め

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | 本モジュールはデータベース操作を行わない |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| AssertionDefect | ランタイムエラー | foldl/foldrに空シーケンスを渡した場合 | 入力シーケンスの事前チェック |
| IndexDefect | 範囲エラー | delete関数で範囲外のスライスを指定した場合 | 有効な範囲を指定 |

### リトライ仕様

該当なし（同期処理のためリトライ不要）

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

該当なし（データベース操作なし）

## パフォーマンス要件

- **map/filter**: O(n)の時間計算量
- **foldl/foldr**: O(n)の時間計算量
- **deduplicate(isSorted=true)**: O(n)、isSorted=falseの場合はO(n^2)
- **toSeq**: lenが取得可能な場合は事前に領域確保し効率化
- **sinkパラメータ**: move semanticsにより不要なコピーを削減

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

- 本モジュールはメモリ安全性を保証（境界チェック有効時）
- ユーザー提供のクロージャは呼び出し元の責任で安全性を担保
- オーバーフローチェックは`unCheckedInc`マクロにより一部で無効化（パフォーマンス最適化のため）

## 備考

- Nim 1.1以降で追加された機能には`since`プラグマが付与されている
- `mapIt`、`filterIt`等のテンプレートは`it`変数をinjectする
- `sugar`モジュールの`collect`マクロとの併用が推奨される場面がある

---

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

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

### 推奨読解順序

#### Step 1: モジュール構造とインポートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sequtils.nim | `lib/pure/collections/sequtils.nim` | 1-96行目: モジュールドキュメントとインポート |

**読解のコツ**:
- 1-81行目のドキュメントコメントでモジュールの目的と使用例を把握
- `runnableExamples`ブロック（41-61行目、64-72行目）で実際の使用パターンを確認
- 82-95行目でインポートとコンパイル条件を理解

#### Step 2: 基本的な変換・フィルタ関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sequtils.nim | `lib/pure/collections/sequtils.nim` | 463-535行目: map/apply関数群 |
| 2-2 | sequtils.nim | `lib/pure/collections/sequtils.nim` | 537-615行目: filter/keepIf関数群 |

**主要処理フロー**:
1. **463-487行目**: `map`関数 - 新規シーケンス生成し各要素に`op`を適用
2. **489-535行目**: `apply`関数群 - 既存シーケンスをin-placeで変更（3つのオーバーロード）
3. **537-558行目**: `filter`イテレータ - 述語を満たす要素をyield
4. **560-585行目**: `filter`関数 - 述語を満たす要素で新規シーケンス生成
5. **587-615行目**: `keepIf`関数 - 述語を満たす要素のみ保持（in-place変更）

#### Step 3: テンプレートベースの操作を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sequtils.nim | `lib/pure/collections/sequtils.nim` | 715-743行目: filterItテンプレート |
| 3-2 | sequtils.nim | `lib/pure/collections/sequtils.nim` | 1069-1132行目: mapItテンプレート |
| 3-3 | sequtils.nim | `lib/pure/collections/sequtils.nim` | 951-1025行目: foldl/foldrテンプレート |

**主要処理フロー**:
- **715-743行目**: `filterIt` - `it`変数をinjectし、述語式で要素をフィルタ
- **1069-1132行目**: `mapIt` - `it`変数をinjectし、変換式を適用。クロージャ生成時は`map`にフォールバック
- **951-998行目**: `foldl` - 左から右への畳み込み。`a`と`b`変数をinject
- **1027-1067行目**: `foldr` - 右から左への畳み込み

#### Step 4: シーケンス生成・変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sequtils.nim | `lib/pure/collections/sequtils.nim` | 913-949行目: toSeqテンプレート |
| 4-2 | sequtils.nim | `lib/pure/collections/sequtils.nim` | 149-237行目: concat/count/cycle/repeat/deduplicate |

**主要処理フロー**:
- **872-911行目**: `toSeq1`/`toSeq2`ヘルパーテンプレート - 型付き/イテレータ用の分岐
- **913-949行目**: `toSeq` - whenコンパイル時分岐で適切な実装を選択
- **124-147行目**: `concat` - 複数シーケンスを連結、事前にサイズ計算
- **180-196行目**: `cycle` - シーケンスをn回繰り返し
- **211-237行目**: `deduplicate` - isSorted最適化付き重複排除

#### Step 5: zip/unzipと検査関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | sequtils.nim | `lib/pure/collections/sequtils.nim` | 349-405行目: zip/unzip |
| 5-2 | sequtils.nim | `lib/pure/collections/sequtils.nim` | 793-870行目: all/allIt/any/anyIt |

**主要処理フロー**:
- **349-391行目**: `zip` - 2つのシーケンスをタプルのシーケンスに結合（短い方に合わせる）
- **393-405行目**: `unzip` - タプルシーケンスを2つのシーケンスに分離
- **793-809行目**: `all` - 全要素が述語を満たすか検査
- **835-851行目**: `any` - いずれかの要素が述語を満たすか検査

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

```
sequtils.nim (ユーザーコード)
    │
    ├─ 変換系
    │   ├─ map(s, op) → newSeq + loop
    │   ├─ mapIt(s, op) → [内部: evalOnceAs → newSeq + loop] or map fallback
    │   └─ apply(s, op) → in-place modification
    │
    ├─ フィルタ系
    │   ├─ filter(s, pred) → newSeq + conditional add
    │   ├─ filterIt(s, pred) → [内部: newSeq + it injection]
    │   └─ keepIf(s, pred) → in-place shrink
    │
    ├─ 畳み込み系
    │   ├─ foldl(s, op) → sequential accumulation (left)
    │   └─ foldr(s, op) → sequential accumulation (right)
    │
    ├─ 検査系
    │   ├─ all(s, pred) → short-circuit evaluation
    │   ├─ any(s, pred) → short-circuit evaluation
    │   └─ count(s, x) → linear scan
    │
    └─ 生成系
        ├─ toSeq(iter) → [内部: toSeq1/toSeq2分岐]
        ├─ concat(seqs) → size計算 + copy
        └─ cycle(s, n) → repeated copy
```

### データフロー図

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

openArray[T] ─────────▶ map/mapIt ──────────────────▶ seq[S] (新規)
     │
     ├────────────────▶ filter/filterIt ────────────▶ seq[T] (新規)
     │
     ├────────────────▶ apply/applyIt ──────────────▶ var seq[T] (変更)
     │
     ├────────────────▶ foldl/foldr ────────────────▶ T (単一値)
     │
     ├────────────────▶ all/any ────────────────────▶ bool
     │
     └────────────────▶ count ──────────────────────▶ int

seq[T], seq[S] ───────▶ zip ────────────────────────▶ seq[(T, S)]

seq[(T, S)] ──────────▶ unzip ──────────────────────▶ (seq[T], seq[S])

iterator: T ──────────▶ toSeq ──────────────────────▶ seq[T]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sequtils.nim | `lib/pure/collections/sequtils.nim` | ソース | メインモジュール（全機能実装） |
| sugar.nim | `lib/pure/sugar.nim` | ソース | collect マクロ、=> 演算子（併用推奨） |
| algorithm.nim | `lib/pure/algorithm.nim` | ソース | sort、binarySearch等（関連モジュール） |
| macros.nim | `lib/core/macros.nim` | ソース | mapLiterals マクロ実装に使用 |
| typetraits.nim | `lib/pure/typetraits.nim` | ソース | supportsCopyMem判定に使用 |
