# 機能設計書 132-Missing型

## 概要

本ドキュメントは、Julia の `Missing` 型および `missing` 値による SQL 風の3値論理と欠損値処理機能について、その設計・処理仕様を記述するものである。

### 本機能の処理概要

Missing 型は、データの欠損（値が存在しない状態）を型安全に表現する機能である。SQL の NULL に相当する概念を Julia の型システムで実現し、欠損値の伝播（propagation）を自動的に行う。

**業務上の目的・背景**：統計処理やデータ分析において、欠損値は避けられない現実である。Missing 型は、欠損値を明示的に型で表現することで、コンパイル時の型チェックと実行時の安全な欠損値伝播を両立する。SQL の NULL セマンティクスに慣れたユーザーにとって直感的に扱える設計となっている。

**機能の利用シーン**：データフレーム操作、統計計算、データベースクエリ結果の処理、センサーデータの欠損処理、アンケートの未回答項目処理など、データに欠損が含まれるあらゆる場面で利用される。

**主要な処理内容**：
1. `Missing` 型と `missing` シングルトン値の提供
2. 算術演算子への Missing 伝播（`missing + 1` => `missing`）
3. 比較演算子での3値論理（`missing == 1` => `missing`、`isequal(missing, missing)` => `true`）
4. ビット演算での短絡評価（`false & missing` => `false`、`true | missing` => `true`）
5. `skipmissing` イテレータによる欠損値のスキップ
6. `coalesce` / `@coalesce` による欠損値のフォールバック
7. 型昇格規則（`promote_rule`）による `Union{T, Missing}` 型の自動導出

**関連システム・外部連携**：Julia の型昇格システム（promotion.jl）、イテレータプロトコル、mapreduce フレームワーク、配列システムと連携する。

**権限による制御**：特に権限による制御はない。

## 関連画面

本機能は特定の画面との紐付けはない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | REPLやスクリプトから missing 値を含むデータの演算・フィルタリングに利用される |

## 機能種別

データ型 / 計算処理 / バリデーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| missing | Missing | - | Missing 型のシングルトンインスタンス | - |
| itr | AbstractArray等 | Yes（skipmissing） | 欠損値を含むイテラブル | イテレータプロトコル準拠 |
| x... | Any | Yes（coalesce） | missing でない最初の値を返す可変長引数 | - |

### 入力データソース

Julia のコード内での直接利用。データフレーム、配列、データベースクエリ結果など。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| missing 伝播結果 | Missing | 演算にmissingが含まれる場合の伝播結果 |
| 3値論理結果 | Missing / Bool | 比較演算の結果（missing または Bool） |
| skipmissing イテレータ | SkipMissing{T} | 欠損値をスキップするイテレータ |
| coalesce 結果 | T / Missing | 最初の非missing値、またはmissing |

### 出力先

呼び出し元への戻り値。

## 処理フロー

### 処理シーケンス

```
1. Missing 型の定義（essentials.jl で定義済み）
   └─ Missing は Core で定義されるシングルトン型
2. 型昇格規則の定義
   └─ promote_rule(Missing, S) = Union{S, Missing}
3. 算術演算子への Missing 伝播定義
   └─ +, -, *, /, ^, mod, rem 等の二項演算子
4. 比較演算子での 3値論理定義
   └─ ==, <, isless, isequal 等
5. ビット演算の短絡評価定義
   └─ &, |, xor での Bool との組み合わせ
6. 単項演算子・関数への Missing 伝播定義
   └─ !, ~, abs, sign, zero, one 等
7. skipmissing イテレータの実装
   └─ SkipMissing 型とイテレータプロトコル
8. coalesce / @coalesce の実装
   └─ 最初の非missing値を返すフォールバック機構
```

### フローチャート

```mermaid
flowchart TD
    A["演算呼び出し: op(x, y)"] --> B{"x または y が Missing?"}
    B -->|No| C["通常の演算結果"]
    B -->|Yes| D{"演算子の種別"}
    D -->|算術演算| E["missing を返す"]
    D -->|比較演算| F{"isequal?"}
    F -->|Yes| G["isequal(missing, missing) = true"]
    F -->|No| H["missing を返す"]
    D -->|ビット演算| I{"短絡評価可能?"}
    I -->|"false & missing"| J["false を返す"]
    I -->|"true OR missing"| K["true を返す"]
    I -->|その他| L["missing を返す"]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-132-01 | Missing 伝播 | 算術演算で1つでも missing があれば結果は missing | 算術演算（+, -, *, / 等） |
| BR-132-02 | 3値論理（==） | `==` での比較で missing があれば結果は missing | `==` 演算子 |
| BR-132-03 | 値等価性 | `isequal(missing, missing)` は `true` を返す | `isequal` 関数 |
| BR-132-04 | 順序関係 | `isless(missing, x)` は `false`、`isless(x, missing)` は `true` | `isless` 関数。missing は全ての値より大きいとみなされる |
| BR-132-05 | ビット短絡 | `false & missing` => `false`、`true | missing` => `true` | Bool とのビット演算 |
| BR-132-06 | 型昇格 | `promote_rule(Missing, S)` は `Union{S, Missing}` を返す | 型昇格時 |
| BR-132-07 | skipmissing | missing 値をスキップしてイテレーションする。結果は常にVector | skipmissing + collect |
| BR-132-08 | coalesce | 最初の非missing値を返す。全てmissingならmissingを返す | coalesce 関数 |

### 計算ロジック

**ビット演算の短絡評価**（155-169行目）:
- `(&)(a::Missing, b::Bool)` = `ifelse(b, missing, false)` -- b が false なら結果は確定的に false
- `(|)(a::Missing, b::Bool)` = `ifelse(b, true, missing)` -- b が true なら結果は確定的に true
- `xor(a::Missing, b::Bool)` = `missing` -- xor は常に missing を伝播

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

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

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | MissingException | `skipmissing` で missing インデックスにアクセス | 有効なインデックスのみ使用する |
| - | MissingException | `round(T, missing)` で非Missing型への変換 | `Union{T, Missing}` 型を使用する |
| - | MethodError | `zero(Any)` / `one(Any)` 呼び出し | 具体的な型を指定する |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- Missing は空のシングルトン型であり、メモリオーバーヘッドはゼロ
- `Union{T, Missing}` は Julia コンパイラの Union-splitting 最適化により効率的に処理される
- `SkipMissing` の `mapreduce` は `@simd` を活用した最適化実装を持つ（337行目）
- pairwise reduction による数値安定性の確保（344-358行目）

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

特筆すべきセキュリティ考慮事項はない。

## 備考

- `Missing` 型は `base/essentials.jl` で定義され、`missing.jl` で演算が拡張される
- `nonmissingtype(Union{Int, Missing})` は `Int` を返す（39行目）
- `@coalesce` マクロは短絡評価版で、不要な式の評価を避ける（Julia 1.7以降）
- `float(AbstractArray{Union{T, Missing}})` はelement型を `Union{float(T), Missing}` に変換する（174-178行目）

---

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

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

### 推奨読解順序

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

Missing 型の基本定義は essentials.jl にあり、missing.jl でその振る舞いが定義される。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | essentials.jl | `base/essentials.jl` | Missing 型と missing 定数、ismissing 関数の定義（Core で定義） |
| 1-2 | missing.jl | `base/missing.jl` | **14-16行目**: `MissingException` 構造体の定義 |
| 1-3 | missing.jl | `base/missing.jl` | **39行目**: `nonmissingtype` -- Union型からMissingを除去するユーティリティ |
| 1-4 | missing.jl | `base/missing.jl` | **231-233行目**: `SkipMissing{T}` 構造体 -- skipmissing の内部型 |

**読解のコツ**: `Missing` は Core で `struct Missing end` として定義されるシングルトン型。`missing` は `Missing()` のインスタンス。`ismissing(x)` は `x isa Missing` と同等。

#### Step 2: 型昇格規則を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | missing.jl | `base/missing.jl` | **48-66行目**: `promote_rule` の各特殊化メソッド |

**主要処理フロー**:
- **48行目**: `promote_rule(Missing, S) = Union{S, Missing}` -- 基本規則
- **49行目**: `promote_rule(Union{Nothing, Missing}, S) = Union{S, Nothing, Missing}` -- Nothing との組み合わせ
- **50-59行目**: `>:Union{Nothing, Missing}` 型に対する昇格規則 -- nonmissingtype と nonnothingtype による分解
- **60-66行目**: `>:Missing` 型に対する昇格規則

#### Step 3: 演算子への Missing 伝播を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | missing.jl | `base/missing.jl` | **73-93行目**: 比較演算子（==, <, isless, isequal, isapprox）|
| 3-2 | missing.jl | `base/missing.jl` | **96-113行目**: 単項演算子・関数への Missing 伝播（@eval ループ）|
| 3-3 | missing.jl | `base/missing.jl` | **116-123行目**: 二項算術演算子への Missing 伝播 |
| 3-4 | missing.jl | `base/missing.jl` | **155-169行目**: ビット演算の短絡評価 |

**読解のコツ**: `@eval` ループで多数の演算子に対して一括定義されている。単項演算子は96-104行目で、二項演算子は116-123行目で定義。ビット演算（&, |, xor）は Bool との組み合わせで短絡評価を行うため個別定義がある。

#### Step 4: skipmissing イテレータを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | missing.jl | `base/missing.jl` | **229-233行目**: `skipmissing` 関数と `SkipMissing` 型 |
| 4-2 | missing.jl | `base/missing.jl` | **238-248行目**: `iterate` メソッド -- missing をスキップしながらイテレーション |
| 4-3 | missing.jl | `base/missing.jl` | **250-259行目**: `IndexStyle` / `eachindex` / `keys` / `getindex` |
| 4-4 | missing.jl | `base/missing.jl` | **270-359行目**: 最適化された `mapreduce` 実装 |
| 4-5 | missing.jl | `base/missing.jl` | **382-390行目**: `filter` メソッド |

#### Step 5: coalesce を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | missing.jl | `base/missing.jl` | **415-419行目**: `coalesce` 関数 -- 再帰的に非missing値を探索 |
| 5-2 | missing.jl | `base/missing.jl` | **448-454行目**: `@coalesce` マクロ -- 短絡評価版 |

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

```
missing 値の演算
    |
    +-- 算術演算 (+, -, *, / 等)
    |       └── missing を返す
    |
    +-- 比較演算 (==, <)
    |       └── missing を返す
    |
    +-- isequal / isless
    |       └── Bool を返す (順序定義あり)
    |
    +-- ビット演算 (&, |, xor)
    |       └── 短絡評価: Bool または missing
    |
    +-- skipmissing(itr)
    |       |
    |       +-- SkipMissing{T}
    |       |       |
    |       |       +-- iterate() -- missing をスキップ
    |       |       +-- eachindex() / keys() -- missing インデックスを除外
    |       |       +-- getindex() -- missing インデックスで MissingException
    |       |
    |       +-- mapreduce (最適化実装)
    |               |
    |               +-- _mapreduce (IndexLinear / IndexCartesian)
    |               +-- mapreduce_impl (pairwise reduction)
    |
    +-- coalesce(x...)
    |       └── 再帰的に最初の非missing値を返す
    |
    +-- @coalesce(x...)
            └── 短絡評価で最初の非missing値を返す
```

### データフロー図

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

missing + 1              --> 二項演算 Missing 伝播      --> missing
missing == 1             --> 比較演算 3値論理           --> missing
isequal(missing,missing) --> 値等価性判定               --> true
false & missing          --> ビット短絡評価             --> false
skipmissing([1,missing]) --> SkipMissing iterate        --> [1] (missing除外)
coalesce(missing, 1)     --> 再帰的探索                 --> 1
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| missing.jl | `base/missing.jl` | ソース | Missing型の演算定義、skipmissing、coalesce |
| essentials.jl | `base/essentials.jl` | ソース | Missing型、missing定数、ismissing関数の定義 |
| promotion.jl | `base/promotion.jl` | ソース | promote_rule / promote_type の基盤 |
| reduce.jl | `base/reduce.jl` | ソース | mapreduce の基盤（SkipMissing が特殊化） |
| some.jl | `base/some.jl` | ソース | Some/Nothing 型（Missing と相補的な関係） |
| test/missing.jl | `test/missing.jl` | テスト | Missing 機能の回帰テスト |
