# 機能設計書 84-filter_with_key

## 概要

本ドキュメントは、Hack Standard Library (HSL) の Dict モジュールにおける `filter_with_key` 関数の機能設計を記述する。この関数は、キーと値の両方を引数に取る述語関数が true を返すエントリのみを含む新しい dict を返す機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：データフィルタリングにおいて、値だけでなくキーも条件判定に使用したいケースは多い。例えば、特定の接頭辞を持つキーかつ特定の値を持つエントリのみを抽出する、キーと値の関係性に基づいてフィルタリングする（例：キーが偶数で値も偶数のエントリ）、複合条件でのデータ抽出などである。本関数は、このようなキーと値の両方を考慮したフィルタリング処理を型安全に行うためのユーティリティを提供する。

**機能の利用シーン**：
- キーと値の両方を条件に含めてフィルタリングする場合
- キーと値の関係性を検証してフィルタリングする場合
- 複合条件でエントリを選別する場合
- インデックス（キー）に基づく条件と値に基づく条件を組み合わせる場合

**主要な処理内容**：
1. 入力の KeyedTraversable を順次イテレート
2. 各エントリのキーと値を述語関数に渡す
3. 述語関数が true を返した場合のみ、結果の dict にエントリを追加
4. 結果の dict を返却

**関連システム・外部連携**：本関数は純粋な計算処理であり、外部システムとの連携はない。非同期版として `Dict\filter_with_key_async()` が存在する。

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

## 関連画面

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

## 機能種別

計算処理（フィルタリング）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| $traversable | KeyedTraversable<Tk, Tv> | Yes | フィルタリング対象の KeyedTraversable | なし |
| $predicate | (function(Tk, Tv)[_]: bool) | Yes | キーと値を引数に取り、bool を返す述語関数 | なし |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | dict<Tk, Tv> | 述語関数が true を返したエントリのみを含む dict |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. 結果用の空 dict を初期化
2. $traversable を foreach でイテレート
   ├─ 各エントリのキーと値を述語関数に渡す
   └─ true の場合、結果 dict にエントリを追加
3. 結果の dict を返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[result = dict[]]
    B --> C{次のエントリがあるか?}
    C -->|No| D[result を返却]
    C -->|Yes| E[predicate にキーと値を渡す]
    E --> F{結果は true か?}
    F -->|Yes| G[result にエントリを追加]
    F -->|No| C
    G --> C
    D --> H[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-84-01 | 必須述語 | 述語関数は必須（filter と異なりデフォルトなし） | 常時 |
| BR-84-02 | キーと値の両方評価 | 述語関数はキー（第1引数）と値（第2引数）の両方を受け取る | 常時 |
| BR-84-03 | 元の順序保持 | 結果の dict は元の順序を保持する | 常時 |
| BR-84-04 | キーの保持 | フィルタを通過したエントリは元のキーを保持する | 常時 |

### 計算ロジック

フィルタリング処理:
- 結果 = { (k, v) | (k, v) in $traversable AND $predicate(k, v) == true }

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 型エラー | 不正な型の引数が渡された場合 | Hack型システムによりコンパイル時に検出 |

### リトライ仕様

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

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

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

## パフォーマンス要件

- 時間計算量: O(n * p)、n は $traversable のサイズ、p は述語関数の計算量
- 空間計算量: O(n)

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

- 純粋関数であり、副作用がないためセキュリティリスクは低い
- 述語関数のコンテキスト（ctx）が伝播されるため、述語関数の副作用も追跡可能

## 備考

- 値のみでフィルタリングする場合は `Dict\filter()` を使用すること
- キーのみでフィルタリングする場合は `Dict\filter_keys()` を使用すること
- 非同期の述語関数を使用する場合は `Dict\filter_with_key_async()` を使用すること

---

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

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

### 推奨読解順序

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

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

**読解のコツ**: `(function(Tk, Tv)[_]: bool)` は2引数の関数型で、第1引数がキー、第2引数が値。

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

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

**主要処理フロー**:
1. **103-106行目**: 関数シグネチャ - キーと値を取る述語を必須引数として定義
2. **107行目**: 結果 dict の初期化
3. **108-112行目**: foreach ループでフィルタリング処理
4. **113行目**: 結果を返却

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | select.php | `src/dict/select.php` | filter（79-91行目）- 値のみでフィルタ |
| 3-2 | select.php | `src/dict/select.php` | filter_keys（124-136行目）- キーのみでフィルタ |

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

```
Dict\filter_with_key($traversable, $predicate)
    |
    +-- foreach ($traversable as $key => $value)
            |
            +-- $predicate($key, $value)  [述語の適用]
            |
            +-- $dict[$key] = $value  [条件付きで追加]
```

### データフロー図

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

$traversable ──────────> foreach ループ ─────────────────> dict<Tk, Tv>
(KeyedTraversable)           |
                             +-- 各 key, value に述語を適用
                             |
                             +-- true: 結果に追加
                             +-- false: スキップ

$predicate ───────────> 述語関数の適用
(function(Tk, Tv): bool)    (キーと値の両方を評価)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| select.php | `src/dict/select.php` | ソース | filter_with_key 関数の実装 |
| async.php | `src/dict/async.php` | ソース | filter_with_key_async 関数の実装（非同期版） |
| DictSelectTest.php | `tests/dict/DictSelectTest.php` | テスト | filter_with_key のユニットテスト（160-212行目） |
