# 機能設計書 88-take

## 概要

本ドキュメントは、Hack Standard Library (HSL) の Dict モジュールにおける `take` 関数の機能設計を記述する。この関数は、KeyedTraversable の最初の n 個のエントリを含む新しい dict を返す機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：データ処理において、先頭の一定数の要素のみを取得するパターンは一般的である。例えば、ページネーション処理で1ページ分のデータを取得する場合、上位 N 件のランキングを表示する場合、プレビュー表示で最初の数件のみを表示する場合などに使用される。本関数は、このような先頭要素の取得処理を効率的かつ型安全に行うためのユーティリティを提供する。

**機能の利用シーン**：
- ページネーション処理で1ページ分のデータを取得する場合
- 上位 N 件のデータを取得する場合
- プレビュー表示で先頭の数件のみを取得する場合
- `drop` 関数と組み合わせて部分範囲を取得する場合
- データストリームから一定数のエントリを消費する場合

**主要な処理内容**：
1. n が 0 の場合、即座に空の dict を返却（最適化）
2. n が正の整数であることを検証（0未満は invariant 違反でエラー）
3. 入力の KeyedTraversable を順次イテレート
4. 最初の n 個のエントリを結果の dict に追加
5. n 個に達したら即座にループを終了（早期リターン）
6. 結果の dict を返却

**関連システム・外部連携**：本関数は純粋な計算処理であり、外部システムとの連携はない。

**権限による制御**：本関数は汎用ユーティリティであり、権限による制御は行わない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | 本プロジェクトはUIを持たないライブラリのため画面なし |

## 機能種別

計算処理（コレクション操作）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| $traversable | KeyedTraversable<Tk, Tv> | Yes | 処理対象の KeyedTraversable | なし |
| $n | int | Yes | 取得するエントリ数 | 非負整数（0以上） |

### 入力データソース

関数引数として直接渡される KeyedTraversable オブジェクトと整数値。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | dict<Tk, Tv> | 最初の n エントリを含む dict（要素数が n 未満の場合は全エントリ） |

### 出力先

関数の戻り値として呼び出し元に返却。

## 処理フロー

### 処理シーケンス

```
1. 早期リターン最適化
   └─ $n === 0 の場合、空の dict を返却
2. 入力検証
   └─ $n < 0 の場合、invariant 違反でエラー
3. 結果用の空 dict とカウンタを初期化
4. $traversable を foreach でイテレート
   ├─ 結果 dict にエントリを追加
   ├─ カウンタをインクリメント
   └─ カウンタが $n に達したら break
5. 結果の dict を返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{n === 0 か?}
    B -->|Yes| C[空の dict を返却]
    B -->|No| D{n > 0 か?}
    D -->|No| E[invariant 違反エラー]
    D -->|Yes| F[result = dict[], ii = 0]
    F --> G{次のエントリがあるか?}
    G -->|No| H[result を返却]
    G -->|Yes| I[result にエントリを追加]
    I --> J[ii++]
    J --> K{ii === n か?}
    K -->|Yes| H
    K -->|No| G
    C --> L[終了]
    H --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-88-01 | 非負整数制約 | n は 0 以上の整数でなければならない | 常時 |
| BR-88-02 | 元の順序保持 | 結果の dict は元の順序を保持する | 常時 |
| BR-88-03 | キーの保持 | 取得されたエントリは元のキーを保持する | 常時 |
| BR-88-04 | 部分取得 | 要素数が n 未満の場合、利用可能な全エントリを返す | 常時 |
| BR-88-05 | 早期終了 | n 個のエントリを取得したらイテレーションを終了 | 常時 |

### 計算ロジック

エントリの取得:
- インデックス i（0始まり）のエントリは、i < n の場合に結果に含まれる
- イテレーションは n 個取得した時点で終了（全体をスキャンしない）

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

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

本関数はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | invariant 違反 | n < 0 の場合 | 呼び出し前に n >= 0 を保証する |
| - | 型エラー | 不正な型の引数が渡された場合 | Hack型システムによりコンパイル時に検出 |

### リトライ仕様

本関数は純粋関数であり、リトライの概念は適用されない。

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

本関数はステートレスな純粋関数であり、トランザクション管理は不要。

## パフォーマンス要件

- 時間計算量: O(n)、n は取得するエントリ数（入力全体のサイズではない）
- 空間計算量: O(n)、n は取得するエントリ数

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

- 純粋関数であり、副作用がないためセキュリティリスクは低い
- 入力データの検証は呼び出し元の責任

## 備考

- `drop` 関数と対になる関数で、`take` は最初の n 個を取得、`drop` は最初の n 個をスキップ
- イテレータを使用する場合、take で消費されたエントリは再度取得できないため注意
- n=0 の場合の最適化により、条件分岐で take(0) を呼ぶ場合も効率的

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | select.php | `src/dict/select.php` | take 関数のシグネチャと型パラメータ |

**読解のコツ**: `Tk as arraykey` は Tk が arraykey（int または string）のサブタイプであることを示す制約。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | select.php | `src/dict/select.php` | take 関数の実装（189-207行目） |

**主要処理フロー**:
1. **189-192行目**: 関数シグネチャの定義
2. **193-195行目**: n=0 の場合の早期リターン最適化
3. **196行目**: invariant で n > 0 を検証
4. **197-198行目**: 結果 dict とカウンタの初期化
5. **199-205行目**: foreach ループで取得と早期終了
6. **206行目**: 結果を返却

#### Step 3: 関連関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | select.php | `src/dict/select.php` | drop 関数の実装（51-66行目）- 対になる関数 |

**主要処理フロー**:
- **51-66行目**: drop は take と逆で最初の n 個をスキップ

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

```
Dict\take($traversable, $n)
    |
    +-- if ($n === 0) return dict[]  [早期リターン最適化]
    |
    +-- invariant($n > 0, ...)  [入力検証]
    |
    +-- foreach ($traversable as $key => $value)
            |
            +-- $result[$key] = $value  [エントリを追加]
            |
            +-- if ($ii === $n) break  [早期終了]
```

### データフロー図

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

$traversable ──────> foreach ループ ──────────────────> dict<Tk, Tv>
(KeyedTraversable)      |                               (最大 n エントリ)
                        +-- カウンタ < n: 結果に追加
                        |
                        +-- カウンタ === n: 早期終了

$n ─────────────────> 取得数の制御
(int)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| select.php | `src/dict/select.php` | ソース | take 関数の実装 |
| DictSelectTest.php | `tests/dict/DictSelectTest.php` | テスト | take のユニットテスト（376-437行目） |
