# 機能設計書 75-zip

## 概要

本ドキュメントは、Hack Standard Library（HSL）のVec名前空間が提供する`zip`関数の機能設計を記述する。この関数は、2つのTraversableをペアにして結合し、タプルのvecとして返却する機能を提供する。

### 本機能の処理概要

`Vec\zip`関数は、2つのTraversableを受け取り、対応する位置の要素をタプル（ペア）として組み合わせた新しいvecを返却する。長さが異なる場合は、短い方の長さに合わせて処理される。

**業務上の目的・背景**：データ処理において、2つの関連するコレクションを対応付けて処理する必要がある場面は多い。例えば、キーのリストと値のリストを組み合わせてマッピングを作成する、2つのセンサーからの時系列データを同期させる、テストデータと期待値を組み合わせるなどのケースである。`zip`関数は、このようなペアリング処理を簡潔かつ型安全に実装することを可能にする。

**機能の利用シーン**：
- 2つの配列から対応するペアを作成する
- 名前リストと値リストを組み合わせて連想配列的な構造を作成する
- 複数のデータソースを同期させて処理する
- テストケースで入力と期待値をペアリングする

**主要な処理内容**：
1. 入力として2つのTraversableを受け取る
2. 両方のTraversableをvecに変換する
3. 短い方の長さを計算する
4. 対応するインデックスの要素をタプルとして組み合わせる
5. タプルのvecを返却する

**関連システム・外部連携**：本機能は純粋な関数であり、外部システムとの連携はない。内部でMath\minvaとC\count関数を使用する。

**権限による制御**：本機能は純粋関数（Pure Function）であり、権限による制御は適用されない。

## 関連画面

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

## 機能種別

計算処理 / データ結合

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| $first | Traversable<Tv> | Yes | 最初のコレクション | なし（空コレクションも許容） |
| $second | Traversable<Tu> | Yes | 2番目のコレクション | なし（空コレクションも許容） |

### 入力データソース

関数引数として直接渡される。両方の引数はTraversable型である必要がある。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | vec<(Tv, Tu)> | 対応する位置の要素をタプルとして含むvec |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. 最初のTraversableをvecに変換
   └─ $one = cast_clear_legacy_array_mark($first)
2. 2番目のTraversableをvecに変換
   └─ $two = cast_clear_legacy_array_mark($second)
3. 空のvecを結果として初期化
   └─ $result = vec[]
4. 短い方の長さを計算
   └─ $lesser_count = Math\minva(C\count($one), C\count($two))
5. インデックス0から$lesser_count未満までループ
   └─ for ($i = 0; $i < $lesser_count; ++$i)
6. 対応する要素のタプルを結果に追加
   └─ $result[] = tuple($one[$i], $two[$i])
7. 完成した結果vecを返却
   └─ return $result
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[$firstをvecに変換: $one]
    B --> C[$secondをvecに変換: $two]
    C --> D[result = vec空配列を初期化]
    D --> E[lesser_count = min の長さを計算]
    E --> F[i = 0]
    F --> G{i < lesser_count?}
    G -->|Yes| H[tuple one[i], two[i] をresultに追加]
    H --> I[i++]
    I --> G
    G -->|No| J[resultを返却]
    J --> K[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-75-01 | 短い方基準 | 出力の長さは短い方のTraversableに合わせる | 常時 |
| BR-75-02 | 長い要素切り捨て | 長いTraversableの余剰要素は無視される | 長さが異なる場合 |
| BR-75-03 | 空入力処理 | いずれかが空の場合は空のvecを返す | いずれかが空の場合 |
| BR-75-04 | キー破棄 | KeyedTraversableのキーは破棄される | KeyedTraversable入力時 |
| BR-75-05 | 順序保持 | 入力順序が出力で保持される | 常時 |

### 計算ロジック

- 出力長 = min(len($first), len($second))
- 出力[i] = tuple($first[i], $second[i]) for i in 0..出力長-1

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

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | 本関数は例外をスローしない | - |

### リトライ仕様

本機能にリトライ仕様はない。

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

本機能はデータベーストランザクションを使用しない。

## パフォーマンス要件

- 時間計算量: O(min(m, n)) - mは$firstのサイズ、nは$secondのサイズ
- 空間計算量: O(min(m, n)) - 結果格納用のvec

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

本機能は純粋関数であり、特別なセキュリティ考慮事項はない。

## 備考

- Hackのtuple型は固定長の型付きタプルを表現する
- 3つ以上のTraversableをzipする場合は、複数回の呼び出しを組み合わせる

---

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

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

### 推奨読解順序

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

`zip`関数の出力は、タプル型のvecである。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Hack言語組み込み型 | - | Hackのtuple(Tv, Tu)は固定長の型付きタプルであることを理解する |

**読解のコツ**: HackのtupleはPHPの配列とは異なり、各位置の型が固定されている。tuple(1, 'a')の型は(int, string)となる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | cast.php | `src/vec/cast.php` | cast_clear_legacy_array_mark関数の実装を確認 |
| 2-2 | C\count | HSL C名前空間 | 要素数のカウント関数を理解 |
| 2-3 | Math\minva | HSL Math名前空間 | 可変長引数の最小値関数を理解 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | combine.php | `src/vec/combine.php` | zip関数の定義と実装を確認 |

**主要処理フロー**:
1. **52-55行目**: 関数シグネチャ - 2つのTraversableを受け取り、タプルのvecを返す
2. **56-57行目**: 両方のTraversableをvecに変換
3. **58行目**: 空の結果vecを初期化
4. **59行目**: Math\minvaとC\countで短い方の長さを計算
5. **60-62行目**: forループで対応する要素をタプル化
6. **63行目**: 結果を返却

#### Step 4: テストケースを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | VecCombineTest.php | `tests/vec/VecCombineTest.php` | zip関数のテストケースを確認 |

**主要処理フロー**:
- **51-114行目**: provideTestZipメソッドで豊富なテストデータを提供
- **57-58行目**: 空のvec同士のzipは空vecを返す
- **59-60行目**: 片方が空の場合も空vecを返す
- **61-65行目**: 同じ長さのvecのzip
- **66-70行目**: 異なる型のzipが可能
- **78-81行目**: 長さが異なる場合、短い方に合わせる
- **116-124行目**: 実際のテスト実行メソッド

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

```
呼び出し元コード
    │
    └─ Vec\zip($first, $second)
           │
           ├─ cast_clear_legacy_array_mark($first) → $one
           │
           ├─ cast_clear_legacy_array_mark($second) → $two
           │
           ├─ Math\minva(C\count($one), C\count($two)) → $lesser_count
           │
           └─ for ループ
                  └─ tuple($one[$i], $two[$i]) を結果に追加
```

### データフロー図

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

$first: Traversable<Tv>    ───┐
                              │
                              ├──▶  インデックスで対応付け  ───▶  vec<(Tv, Tu)>
                              │     タプルを生成
$second: Traversable<Tu>   ───┘

例:
vec[1, 2, 3]               ───┐
                              ├──▶  zip処理  ───▶  vec[tuple(1, 'a'), tuple(2, 'b'), tuple(3, 'c')]
vec['a', 'b', 'c']         ───┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| combine.php | `src/vec/combine.php` | ソース | zip関数の実装 |
| cast.php | `src/vec/cast.php` | ソース | cast_clear_legacy_array_mark関数の実装 |
| VecCombineTest.php | `tests/vec/VecCombineTest.php` | テスト | zip関数のユニットテスト |
