# 機能設計書 97-Keyset\intersect

## 概要

本ドキュメントは、Hack Standard Library (HSL) の `HH\Lib\Keyset\intersect` 関数の機能設計について記述する。この関数は、複数のTraversableの共通要素（積集合）を計算し、keysetとして返す機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：
複数のデータセットから共通する要素を抽出する処理は、権限の共通部分の計算、共通タグの抽出、重複データの検出などで必要とされる。本機能は、複数のTraversableに共通して存在する要素のみを抽出し、keysetとして返す。これにより、集合演算の積集合を効率的に計算でき、複数条件を満たすデータの抽出が容易になる。

**機能の利用シーン**：
- 複数のユーザーグループに共通するユーザーIDを取得する際
- 複数の検索条件をすべて満たすアイテムを抽出する際
- 複数のタグセットに共通するタグを見つける際
- 権限の共通部分を計算する際

**主要な処理内容**：
1. 最初のTraversableをkeysetに変換
2. 2番目以降のTraversableと順番に積集合を計算
3. 各ステップで共通要素のみを残す
4. 最終的な積集合をkeysetとして返却

**関連システム・外部連携**：
- `Keyset\diff`（差集合）と対になる関数
- 内部で`C\contains_key`関数を使用
- arraykey制約により、int型とstring型のみを要素として受け付ける

**権限による制御**：
特になし。純粋な計算処理のため、権限による制御は行わない。

## 関連画面

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

## 機能種別

計算処理（集合演算）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| $first | Traversable<Tv> | Yes | 積集合計算の基準となるコレクション | Tvはarraykey制約 |
| $second | Traversable<Tv> | Yes | 2番目のコレクション | Tvはarraykey制約 |
| ...$rest | Container<Tv> | No | 追加のコレクション（可変長引数） | Tvはarraykey制約 |

### 入力データソース

関数呼び出し時の引数として渡されるTraversable/Containerインスタンス。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | keyset<Tv> | すべてのTraversableに共通する要素のkeyset |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. 早期リターンチェック
   └─ $firstまたは$secondが空の場合、空のkeysetを返却
2. $firstをkeysetに変換
3. $restに$secondを追加
4. 各Traversableについて積集合を計算
   └─ 現在の積集合の各要素について、対象Traversableに含まれるか確認
   └─ 含まれる要素のみを新しい積集合として保持
   └─ 積集合が空になれば早期リターン
5. 結果返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{$first or $second is empty?}
    B -->|Yes| C[空のkeysetを返却]
    B -->|No| D[$intersection = keyset($first)]
    D --> E[$rest[] = $second]
    E --> F{$restの各traversableを走査}
    F --> G[$next_intersection = keyset[]]
    G --> H[$keyed_traversable = keyset(traversable)]
    H --> I{$intersectionの各valueを走査}
    I --> J{valueは$keyed_traversableに存在?}
    J -->|Yes| K[$next_intersection[] = value]
    J -->|No| L[次の要素へ]
    K --> L
    L --> I
    I -->|完了| M{$next_intersection is empty?}
    M -->|Yes| C
    M -->|No| N[$intersection = $next_intersection]
    N --> F
    F -->|完了| O[$intersectionを返却]
    C --> P[終了]
    O --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 厳密比較 | 要素の比較は厳密等価（===）で行う | 全ての比較時 |
| BR-02 | 全コレクション共通 | 結果にはすべてのコレクションに存在する要素のみ含まれる | 常時 |
| BR-03 | 空集合の早期リターン | いずれかのコレクションが空、または途中で積集合が空になれば処理終了 | 空検出時 |

### 計算ロジック

積集合の計算は集合演算の A ∩ B ∩ C ∩ ... に相当する。
- 時間計算量: O(n + m) - nは$firstのサイズ、mは$second以降の合計サイズ
- 空間計算量: O(n) - nは$firstのサイズ

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

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

該当なし。本機能はインメモリでのコレクション操作のみを行う。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | TypeError | arraykeyでない型の要素を含むTraversableを渡した場合 | int/string型のみを使用 |

### リトライ仕様

該当なし。純粋関数であり、同じ入力に対しては常に同じ結果を返す。

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

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

## パフォーマンス要件

- 時間計算量: O(n + m)
- 空間計算量: O(n)
- 早期リターンの最適化により、空の積集合が検出された時点で処理を終了

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

特になし。純粋なデータ変換処理であり、外部リソースへのアクセスは行わない。

## 備考

- $restの各Traversableは内部でkeysetに変換され、O(1)のcontains_key操作が可能になる
- 途中で積集合が空になった場合の早期リターンにより、不要な計算を回避

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | (Hack言語仕様) | - | keysetは一意のarraykeyのみを格納し、O(1)の存在確認が可能 |

**読解のコツ**: 積集合の計算では、各ステップで中間結果をkeysetに保持し、次のTraversableとの共通部分を求める。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | select.php | `src/keyset/select.php` | intersect関数の実装本体 |

**主要処理フロー**:
1. **161-168行目**: ドキュメントコメント - 機能と計算量の説明
2. **169-173行目**: 関数シグネチャ - 可変長引数$rest
3. **174-177行目**: 空チェックと早期リターン
4. **178行目**: $firstをkeysetに変換
5. **179行目**: $restに$secondを追加
6. **180-192行目**: 各Traversableとの積集合を計算
7. **193行目**: 結果を返却

#### Step 3: 依存関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | introspect.php | `src/c/introspect.php` | C\contains_keyの実装 |

**主要処理フロー**:
- **72-81行目**: C\contains_key - O(1)のキー存在確認

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

```
Keyset\intersect($first, $second, ...$rest)
    │
    ├─ keyset($first)  [PHP/Hack組み込み: keyset変換]
    │
    ├─ keyset($traversable)  [各Traversableをkeysetに変換]
    │
    └─ C\contains_key($keyed_traversable, $value)
           └─ \array_key_exists($key, $container)
```

### データフロー図

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

$first (Traversable) ──▶ keyset変換 ──▶┐
                                       │
$second (Traversable) ──▶ keyset変換 ─▶ 積集合計算 ──▶ keyset<Tv>
                                       │
$rest (Container...) ──▶ keyset変換 ─▶┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| select.php | `src/keyset/select.php` | ソース | intersect関数の実装 |
| introspect.php | `src/c/introspect.php` | ソース | contains_key関数 |
| KeysetSelectTest.php | `tests/keyset/KeysetSelectTest.php` | テスト | intersect関数のユニットテスト |
