---
title: Iterator とクロージャー
url: https://doc.liz6.com/ja/rust/10-standard-library-depth/01-iterator-and-closures
locale: ja
area: rust
tags:
- Rust
- Iterator
- Closure
- Zero-cost
- Lazy Evaluation
- rust
- standard-library-depth
date: 2026-06-30
modified: 2026-07-16
description: Iterator は Rust において最も成功した抽象化です。map/filter/chain などのアダプタは遅延評価（呼び出されない限り実行されない）であり、コンパイル時にインライン展開されて手書きのループと同等の機械語に最適化されます（ゼロコスト）。Fn/FnMut/FnOnce の3種類のクロージャートレイトは3つのキャプチャ方式に対応し、collect はイテレータをコンテナに収束させます。チェーン操作は読みやすさからゼロコストへ、一歩で到達します。
---

# Iterator とクロージャー

> Iterator は Rust において最も成功した抽象化です。map/filter/chain などのアダプタは遅延評価（呼び出されない限り実行されない）であり、コンパイル時にインライン展開されて手書きのループと同等の機械語に最適化されます（ゼロコスト）。Fn/FnMut/FnOnce の3種類のクロージャートレイトは3つのキャプチャ方式に対応し、collect はイテレータをコンテナに収束させます。チェーン操作は読みやすさからゼロコストへ、一歩で到達します。

## Iterator trait: 反復の根源

```rust
pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
    // デフォルト実装を持つメソッドが70以上存在 — これらはすべて next() に基づいている
}
```

`next()` が唯一実装必須のメソッドです。他のすべてのメソッド（`map`, `filter`, `take`, `fold`, `collect` など）は、`next()` を基にしたデフォルト実装です。つまり、`next()` を実装するだけで、あなたの型は自動的にイテレータエコシステム全体を利用可能になります。

## 遅延評価: イテレータは「駆動」されるまで何もしない

```rust
let v: Vec<i32> = (0..10)
    .filter(|x| x % 2 == 0)         // 発生しない — 単にチェーンを構築しているだけ
    .map(|x| x * 2)                  // 発生しない
    .take(3)                         // 発生しない
    .collect();                      // ここで発生! すべてのアダプタが「駆動」される
// → [0, 4, 8]
```

このコードは `collect()` が呼ばれるまで、要素を1つとして処理しません。`collect()` が `next()` を呼び出すと、それは `take` に要求し、`take` は `map` に要求し、`map` は `filter` に要求し、`filter` は `0..10` に要求します。これにより「プル」型のチェーンが形成されます。これは Python のリスト内包表記のような即時評価（eager evaluation）とは根本的に異なります。

## 主要なアダプタ

| アダプタ | 役割 | 評価タイミング |
|---------|------|---------|
| `map` | 各要素を変換 | 遅延 |
| `filter` | 条件を満たす要素を保持 | 遅延 |
| `take(n)` | 先頭 n 個を取得後、停止 | 遅延 |
| `skip(n)` | 先頭 n 個をスキップ | 遅延 |
| `enumerate` | インデックス `(index, item)` を付加 | 遅延 |
| `chain` | 2つのイテレータを連結 | 遅延 |
| `flat_map` | 各要素をイテレータに展開 | 遅延 |
| `fold` | 累積（リデュース） | 即時（イテレータを消費） |
| `collect` | コレクションとして収集 | 即時 |

## 3種類のクロージャートレイト: FnOnce → FnMut → Fn

これら3つのトレイトは制約のチェーンを形成します:

```
FnOnce: 1回しか呼び出せない — キャプチャした値を消費（所有権の移動）
FnMut:  `&mut self` — キャプチャした値を変更可能、複数回呼び出し可能
Fn:     `&self` — キャプチャした値は読み取り専用、複数回呼び出し可能、最も汎用的
```

- すべてのクロージャーはデフォルトで `FnOnce` を実装します
- クロージャーがキャプチャした値を消費しない場合 → `FnMut` も実装
- クロージャーがキャプチャした値を変更しない場合 → `Fn` も実装

```rust
let s = String::from("hi");
let f = || s;                        // s がクロージャーにムーブされる — これは FnOnce
// f() は1回しか呼び出せない — 呼び出し後、s は消費され、f は再度呼び出せない

let mut v = vec![1, 2, 3];
let mut f = || { v.push(4); };       // v を変更 — FnMut（複数回呼び出し可能）

let x = 42;
let f = || println!("{}", x);        // 読み取り専用 — Fn（最も汎用的）
```

## ゼロコストのイテレーション

リリースモードでは、イテレータチェーンは通常、コンパイラによって単一のループに「融合」されます。`map`, `filter`, `collect` の連続する呼び出しは、追加の割り当てや仮想関数呼び出しなしで、等価な for ループに最適化されます。これが、イテレータにおける Rust のゼロコスト抽象化の現れです。

## 参考

- **Rust Book**: 第13章
- **Rust Reference**: Fn traits, Iterator

*Keywords: Iterator, lazy evaluation, collect, Fn, FnMut, FnOnce, adaptor, zero-cost*
