Skip to content

第 11 章: 不変データとパイプライン処理

11.1 はじめに

前章ではクロージャとイテレータを使った高階関数を学びました。この章では イテレータチェーン によるパイプライン処理と 不変データ の考え方を深めます。

11.2 Rust の不変性

Rust では変数はデフォルトで不変(immutable)です。

let x = 5;       // 不変(デフォルト)
let mut y = 10;  // 可変(明示的)

FizzBuzzValue#[derive(Clone)] で値のコピーが可能ですが、フィールドは非公開なため外部から変更できません。これにより不変性が自然に保証されます。

11.3 イテレータチェーン(パイプライン)

Rust のイテレータは 遅延評価 され、チェーンで連結できます。

// パイプライン: filter → map → collect
let fizz_numbers: Vec<i32> = list.value().iter()
    .filter(|v| v.value() == "Fizz")
    .map(|v| v.number())
    .collect();

fold(集約)

// 全 FizzBuzz 値を改行区切りで連結
let joined = list.value().iter()
    .map(|v| v.value().to_string())
    .fold(String::new(), |acc, v| {
        if acc.is_empty() { v } else { format!("{}\n{}", acc, v) }
    });

take(先頭 N 件)

let first_five: Vec<String> = list.value().iter()
    .take(5)
    .map(|v| v.value().to_string())
    .collect();

group_by 相当の処理

Rust の標準ライブラリには group_by がないため、HashMap を使って実装します。

use std::collections::HashMap;

pub fn group_by_value(&self) -> HashMap<String, Vec<&FizzBuzzValue>> {
    let mut groups: HashMap<String, Vec<&FizzBuzzValue>> = HashMap::new();
    for v in &self.list {
        groups.entry(v.value().to_string()).or_default().push(v);
    }
    groups
}

pub fn count_by_value(&self) -> HashMap<String, usize> {
    self.group_by_value().into_iter()
        .map(|(k, v)| (k, v.len()))
        .collect()
}

11.4 FizzBuzzList のパイプライン操作

impl FizzBuzzList {
    pub fn take(&self, n: usize) -> Vec<&FizzBuzzValue> {
        self.list.iter().take(n).collect()
    }

    pub fn join(&self, separator: &str) -> String {
        self.list.iter()
            .map(|v| v.value().to_string())
            .collect::<Vec<_>>()
            .join(separator)
    }

    pub fn reduce<F>(&self, f: F) -> String
    where
        F: Fn(String, &FizzBuzzValue) -> String,
    {
        self.list.iter().fold(String::new(), |acc, v| f(acc, v))
    }
}

11.5 まとめ

概念 Rust PHP Go
不変デフォルト let x = 5
パイプライン .iter().filter().map().collect() array_filterarray_map for ループのチェーン
fold .fold(init, f) array_reduce($arr, f, init) for + 累積変数
遅延評価 イテレータは遅延

次章では、Result/Option 型を使ったエラーハンドリングと型安全性を学びます。