"例外が許されるということは、設計者がエラーを曖昧に扱ってもいいという合意である。"
多くのプログラミング言語において、エラーは「例外」として扱われる。
それは、関数の振る舞いとは独立した、特殊な“割り込み的構造”だ。
try-catch-finally、throw、raise——それらは予測されない振る舞いを「あとから包み込む」構文だった。
Rustはこのパラダイムを拒絶する。
Rustが提供するのは、例外なき世界であり、「エラーもまた値である」という構文的真理である。
この章では、Rustにおける Result<T, E>
を中心に、例外のない設計がなぜ誠実なのかを掘り下げていく。
Result:エラーもまた“構造化された状態”である
enum Result<T, E> {
Ok(T),
Err(E),
}
この定義において重要なのは、「成功」と「失敗」が同等に扱われているという点だ。
片方は正常系、片方は異常系という“感情的”な扱いではなく、
どちらも「起こりうる状態」として設計段階で定義される。
そして、呼び出し元のコードはそれを必ず扱わなければならない。
match do_something() {
Ok(value) => println!("Success: {}", value),
Err(e) => eprintln!("Error: {}", e),
}
これにより、「エラーを考慮しない」という設計上の怠惰が、構文レベルで許されなくなる。
エラー処理が“設計の責務”としてコードに現れる世界
例外ベースの言語では、関数のシグネチャに**「この関数が例外を出すか否か」が書かれていないことが多い。
Rustでは Result
の戻り値がそのままエラー可能性の契約**となる。
fn read_file(path: &str) -> Result<String, std::io::Error>
この関数は、「失敗する可能性がある」ということを構文として示している。
関数と設計の責任が一致しているのだ。
“投げる”のではなく、“返す”ことが信頼を生む
例外はコントロールフローを破壊する。
どこでthrowされたか、どこでcatchされるかはしばしば不透明な階層をまたぐ。
対してRustの Result
は、常に「返される値」として文脈に残る。
それは、制御の流れを壊さず、エラーを明示的に文脈へと渡す構文である。
fn process() -> Result<(), String> {
let data = load_data()?; // 詳細は次章で扱う
validate(&data)?;
Ok(())
}
このように、エラーは制御不能な事象ではなく、“処理の帰結”として返される。
Result型は「振る舞いのすべてをコード化する」構文である
Resultを使うということは、「この関数がどういう世界を扱っているか」を明示することだ。
- 成功する場合はどうなるか
- 失敗した場合は何を返すか
- それに対して、呼び出し側は何を選ぶか
これは設計思想を“分岐可能な構文”へと翻訳する行為である。
組み合わせ可能な失敗:map / and_then による関数合成
Result
はただの構文的保険ではない。
それは、関数型的な合成が可能な、失敗を伴う計算の文脈でもある。
fn double(x: i32) -> Result<i32, String> {
if x > 100 {
Err("Too large".to_string())
} else {
Ok(x * 2)
}
}
fn transform(val: Result<i32, String>) -> Result<i32, String> {
val.map(|x| x + 10)
}
これは、文脈を保ったまま処理を連鎖させるという設計美を持っている。
“無視”を許さないという強さ
例外ベースの言語では、例外をcatchしなければプログラムが落ちる。
それゆえ、開発者はcatchを入れるが、何を捕まえているのか明確でないことが多い。
Rustでは、Result
を扱わないとコンパイルが通らない。
“失敗を考慮しない設計”が物理的に存在できない。
それは強制ではない。
設計に対する誠実さの最小単位なのだ。
Result型は「予測不可能性の構文的可視化」である
世界は予測できない。
ファイルは消えるし、ネットワークは落ちるし、入力は破損する。
Result<T, E>
は、その予測不可能性を「構文に昇華する」手段である。
それは**“壊れることがある”という現実を、設計に組み込む思想**である。
結語:例外のない世界は、設計者の誠実によって成立する
Rustの Result
は、ただのテクニカルな手段ではない。
それは、「失敗とは設計すべき構造である」という言語からの哲学的メッセージだ。
例外を廃し、結果を明示的に返す構文。
それによって、開発者はエラーに対して責任を持つ。
そしてその責任こそが、設計に信頼をもたらす唯一の根拠である。
"失敗を隠すな。それを構文に取り込み、設計に正直であれ。"