# 機能設計書 26-配列操作（Array）

## 概要

本ドキュメントは、FSharp.Coreライブラリにおける配列操作モジュール（Array）の設計を記述する。この機能は、F#の配列に対する各種操作関数群を提供する。

### 本機能の処理概要

F#の配列（'T array）に対する操作関数を提供するモジュール。map、filter、fold、sort等の高階関数から、length、head、tail等の基本操作まで、配列処理に必要な関数を網羅的に提供する。

**業務上の目的・背景**：配列はF#プログラムで最も基本的なデータ構造の一つであり、パフォーマンス重視の処理や.NETとの相互運用で頻繁に使用される。Arrayモジュールは、関数型プログラミングのスタイルで配列を操作するための統一的なAPIを提供し、コードの可読性と保守性を向上させる。

**機能の利用シーン**：データの変換処理、フィルタリング、集計、検索、ソート、グループ化など、配列を使用するあらゆる場面で利用される。

**主要な処理内容**：
1. 生成関数: init, create, zeroCreate, replicate, empty
2. 変換関数: map, mapi, map2, map3, collect
3. フィルタリング: filter, choose, where
4. 集約関数: fold, foldBack, reduce, scan, sum, average
5. 検索関数: find, tryFind, findIndex, exists, forall
6. ソート関数: sort, sortBy, sortWith, sortDescending
7. 分割・結合: take, skip, splitAt, append, concat
8. その他: length, head, tail, isEmpty, contains, distinct

**関連システム・外部連携**：Microsoft.FSharp.Primitives.Basics.Arrayに低レベル実装を委譲。

**権限による制御**：特になし。すべてのユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | ライブラリ機能のためUI関連なし |

## 機能種別

コレクション操作 / ユーティリティライブラリ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| array | 'T array | Yes | 操作対象の配列 | null不可（checkNonNull） |
| mapping | 'T -> 'U | 関数依存 | 変換関数 | - |
| predicate | 'T -> bool | 関数依存 | 条件判定関数 | - |
| folder | 'State -> 'T -> 'State | 関数依存 | 畳み込み関数 | - |

### 入力データソース

呼び出し元のF#コード。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 結果配列 | 'U array | 変換後の配列 |
| 単一値 | 'T または 'State | 集約結果 |
| Option | 'T option | 検索結果（見つからない場合None） |
| bool | bool | 条件判定結果 |

### 出力先

呼び出し元に返却。

## 処理フロー

### 処理シーケンス

```
1. 引数の検証（checkNonNull）
   └─ nullの場合はArgumentNullExceptionをスロー
2. 配列の長さチェック（必要な場合）
   └─ 空配列や長さ不一致のチェック
3. 結果配列の確保（必要な場合）
   └─ zeroCreateUncheckedで未初期化配列を確保
4. forループで各要素を処理
   └─ インデックスベースのループで効率的に処理
5. 結果を返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始: Array.xxx呼び出し] --> B{nullチェック}
    B -->|null| C[ArgumentNullException]
    B -->|valid| D{操作の種類}
    D -->|map等| E[結果配列を確保]
    D -->|fold等| F[初期状態を設定]
    D -->|find等| G[検索開始]
    E --> H[forループで処理]
    F --> I[forループで畳み込み]
    G --> J[while/forで検索]
    H --> K[結果配列を返却]
    I --> L[集約結果を返却]
    J --> M{見つかった?}
    M -->|Yes| N[結果を返却]
    M -->|No| O[None/例外]
    K --> P[終了]
    L --> P
    N --> P
    O --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | null不許可 | 配列引数にnullは許可されない | すべての関数 |
| BR-02 | 不変操作 | 元の配列は変更されない（一部の例外を除く） | ほぼすべての関数 |
| BR-03 | 長さ一致 | map2等では入力配列の長さが一致すること | 複数配列を受け取る関数 |
| BR-04 | 範囲チェック | インデックス指定は有効範囲内であること | get, sub等 |

### 計算ロジック

```fsharp
// map の実装例（340-350行目参照）
let inline map ([<InlineIfLambda>] mapping: 'T -> 'U) (array: 'T array) =
    checkNonNull "array" array
    let res = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked array.Length
    for i = 0 to res.Length - 1 do
        res.[i] <- mapping array.[i]
    res
```

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

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

該当なし。純粋なインメモリ操作。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentNullException | 配列がnullの場合 | 有効な配列を渡す |
| - | ArgumentException | 空配列に対してhead/tail等を呼び出した場合 | 事前にisEmptyでチェック |
| - | KeyNotFoundException | find系で要素が見つからない場合 | tryFind系を使用 |
| - | InvalidOperationException | take/skipで要素が不足している場合 | 事前にlengthをチェック |

### リトライ仕様

リトライは不要。純粋関数のため同じ入力には同じ結果。

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

該当なし。

## パフォーマンス要件

- 各関数はO(n)またはそれ以下の計算量
- sort系はO(n log n)
- インラインの積極的な使用で呼び出しオーバーヘッドを削減
- zeroCreateUncheckedで配列確保を最適化

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

- 配列の境界外アクセスは.NETランタイムにより防止
- 信頼されていないデータの処理でも安全に動作

## 備考

- [<CompiledName("...")>]属性でC#からの呼び出し時の名前を指定
- [<InlineIfLambda>]属性で高階関数のインライン化を促進
- Microsoft.FSharp.Primitives.Basics.Arrayに低レベル実装が存在

---

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

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

### 推奨読解順序

#### Step 1: モジュール構造を理解する

まず、Arrayモジュールの基本構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | array.fs | `src/FSharp.Core/array.fs` | モジュール宣言と属性（14-17行目） |
| 1-2 | array.fs | `src/FSharp.Core/array.fs` | ヘルパー関数（19-24行目）checkNonNull, indexNotFound |

**読解のコツ**: `[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]`により、Array型と同名のモジュールを定義可能にしている。

#### Step 2: 基本関数を理解する

配列の基本操作関数を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | array.fs | `src/FSharp.Core/array.fs` | length（26-29行目） |
| 2-2 | array.fs | `src/FSharp.Core/array.fs` | head/tryHead（280-287行目、73-80行目） |
| 2-3 | array.fs | `src/FSharp.Core/array.fs` | tail（87-94行目） |
| 2-4 | array.fs | `src/FSharp.Core/array.fs` | isEmpty（82-85行目） |
| 2-5 | array.fs | `src/FSharp.Core/array.fs` | empty（96-97行目） |

**主要処理フロー**:
- **26-29行目**: lengthは単純にarray.Lengthを返す
- **280-287行目**: headは空配列チェック後、最初の要素を返す
- **87-94行目**: tailはsubUncheckedで最初の要素を除いた部分配列を返す

#### Step 3: 変換関数を理解する

map、filter等の高階関数を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | array.fs | `src/FSharp.Core/array.fs` | map（340-350行目） |
| 3-2 | array.fs | `src/FSharp.Core/array.fs` | mapi（454-463行目） |
| 3-3 | array.fs | `src/FSharp.Core/array.fs` | map2（384-398行目） |
| 3-4 | array.fs | `src/FSharp.Core/array.fs` | collect（142-153行目） |
| 3-5 | array.fs | `src/FSharp.Core/array.fs` | distinct（325-338行目） |

**主要処理フロー**:
- **340-350行目**: mapは結果配列を確保し、forループで各要素を変換
- **454-463行目**: mapiはインデックスと値を引数に取る
- **384-398行目**: map2は2つの配列を同時に処理（長さチェックあり）

#### Step 4: 集約関数を理解する

fold、reduce等の畳み込み関数を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | array.fs | `src/FSharp.Core/array.fs` | exists（475-485行目） |
| 4-2 | array.fs | `src/FSharp.Core/array.fs` | contains（487-497行目） |
| 4-3 | array.fs | `src/FSharp.Core/array.fs` | iter（318-323行目） |

**主要処理フロー**:
- **475-485行目**: existsはwhileループで条件を満たす要素を探す
- **487-497行目**: containsは値の等価性で検索
- **318-323行目**: iterは各要素に対してアクションを実行

#### Step 5: 生成関数を理解する

配列を生成する関数を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | array.fs | `src/FSharp.Core/array.fs` | init（49-51行目） |
| 5-2 | array.fs | `src/FSharp.Core/array.fs` | zeroCreate（53-58行目） |
| 5-3 | array.fs | `src/FSharp.Core/array.fs` | create（60-71行目） |
| 5-4 | array.fs | `src/FSharp.Core/array.fs` | replicate（129-140行目） |

**主要処理フロー**:
- **49-51行目**: initはBasics.Array.initに委譲
- **53-58行目**: zeroCreateは負のカウントをチェックしてゼロ初期化配列を作成
- **60-71行目**: createは指定値で初期化された配列を作成

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

```
Array モジュール (array.fs)
    │
    ├─ checkNonNull (null検証)
    │
    ├─ 基本操作
    │      ├─ length
    │      ├─ head / tryHead
    │      ├─ tail
    │      ├─ isEmpty
    │      └─ empty
    │
    ├─ 変換操作
    │      ├─ map / mapi / map2 / map3
    │      ├─ collect
    │      ├─ choose
    │      └─ filter
    │
    ├─ 集約操作
    │      ├─ fold / foldBack
    │      ├─ reduce / reduceBack
    │      ├─ scan / scanBack
    │      └─ sum / average
    │
    ├─ 検索操作
    │      ├─ find / tryFind
    │      ├─ findIndex / tryFindIndex
    │      ├─ exists / forall
    │      └─ contains
    │
    └─ Microsoft.FSharp.Primitives.Basics.Array (低レベル実装)
           ├─ init
           ├─ zeroCreateUnchecked
           ├─ subUnchecked
           └─ その他基本操作
```

### データフロー図

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

'T array ───▶ checkNonNull ───▶ 各操作関数 ───▶ 'U array / 'T / bool
    │                              │
    │                              ├─ map: 各要素を変換
    │                              ├─ filter: 条件に合う要素を抽出
    │                              ├─ fold: 畳み込み計算
    │                              └─ find: 条件に合う要素を検索
    │
    └─ mapping/predicate/folder (関数引数)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| array.fs | `src/FSharp.Core/array.fs` | ソース | Arrayモジュールのメイン実装 |
| array.fsi | `src/FSharp.Core/array.fsi` | シグネチャ | 公開APIの定義 |
| local.fs | `src/FSharp.Core/local.fs` | ソース | 内部ヘルパー関数 |
| prim-types.fs | `src/FSharp.Core/prim-types.fs` | ソース | 基本型とPrimitives.Basics.Array |
