"制御されない変化は、システムを腐敗させる。"
状態を変えること、それはプログラミングにおいて“当然”とされてきた。
変数とは「変わることができる値」であり、変更とは機能の実現そのものだった。
だがRustは、その“当たり前”を疑う。
デフォルトを「不変(immutable)」としたことで、設計の意味が逆転した。
この選択は、単なる言語仕様ではない。
変化の意味を構造化し、状態を意識的に制御するという設計哲学である。
なぜRustはすべてを“変更不可”から始めるのか?
Rustでは、変数はデフォルトで不変である。
let x = 5;
x = 6; // エラー: 不変な変数に再代入はできない
変更を許すには、明示的に mut
を指定する必要がある。
let mut x = 5;
x = 6; // OK
これは、「変更してよい」と設計者が明言した変数だけが変わることを許されるという、
“意図の明示”による責任設計なのである。
不変性とは「できること」を減らすのではなく、「考慮を減らす」ことである
変数が変わらないということは、それについて考慮すべき分岐が減るということだ。
- 「この値はどこで変わったのか?」
- 「この変数は共有されているが、同時に変えられていないか?」
- 「テスト時に意図しない副作用が起きていないか?」
不変性は、これらの懸念をすべて構造の外に追いやる。
つまり、考えるべきことが減る=設計の透明性が増すのである。
Rustの不変性は「静的な秩序」である
関数の引数も不変が基本であり、書き換えを意図するならば参照とmutabilityを組み合わせて書く必要がある。
fn update(val: &mut i32) {
*val += 1;
}
このような構文は、意図的に「ここで状態が変わる」と宣言することでのみ、変更を許す。
これは副作用を「許容」するのではなく、「構造に組み込む」ことに他ならない。
不変性と共有:同時性への設計的備え
Rustでは、イミュータブルな値は複数のスレッドから同時に借用可能である。
なぜなら、変化しないものは競合しないからだ。
let data = Arc::new(String::from("Hello"));
let d1 = data.clone();
let d2 = data.clone(); // OK: 不変なら何者とも争わない
この設計が示すのは、不変性がスレッドセーフを“保証するための構造”であるということだ。
イミュータビリティは“信頼の源泉”である
不変性がもたらすのは次の3つである:
- 読んでも安心:他の場所で書き換えられていないと保証される
- 共有しても安心:排他制御のためのmutexが不要になることが多い
- 再利用しても安心:副作用がないことで、コードが構成可能になる
この“安心”こそが、設計における信頼性の土台なのだ。
変更は“最後に選ぶ手段”であるべき
Rustは変化を禁じているわけではない。
むしろ、意図が明確にされた“必要な変化”だけを構文で許している。
これは言語仕様というより、変化に対する倫理的態度である。
- 本当に変更が必要か?
- その変更は設計に含まれているか?
- その変更は共有されるべきか?
こうした問いを書くたびに開発者に突きつける。
だからRustのコードは、設計者の“誠実さ”がにじみ出る。
結語:変わらないということ、それが信頼されるということ
変わるものに人は慎重になる。
変わらないものは、それだけで構造的な信頼を得る。
Rustのイミュータビリティは、
単なる最適化やスレッドセーフのための手段ではない。
それは「設計が信頼に値する状態であるか」を問い続ける仕組みである。
"自由に変えることは自由ではない。変えないことを選べる構造こそが、設計の自由である。"