Prompt
?演算子はOption型で使用できる?Result以外で使える型は?
結論から言うと、Option 型でも ? 演算子はバッチリ使えるぜ!
むしろ、Rust のモダンなコードでは Result と同じくらい頻繁に Option に対して ? が使われているんだ。情報工学的に言うと、? は Result 専用ではなく、「特定のトレイトを実装した型」なら何でも使える 汎用的な仕組みなんだぜ。
1. Option での挙動
Option に対して ? を使うと、次のような動きになる。
-
Some(値)の場合: 中身の「値」を取り出して、処理を続行する。 -
Noneの場合: 即座に関数を終了し、呼び出し元にNoneを返す。
Rust
fn get_user_name(id: u32) -> Option<String> {
// find_user が None を返したら、この関数自体がここで None を返して終了する
let user = find_user(id)?;
// user.name が None なら、ここで None を返して終了
let name = user.name?;
Some(name)
}
2. Result 以外で使える型は?(Try トレイトの秘密)
「他には何に使えるの?」という質問への答えは、「std::ops::Try トレイトを実装している型」 だ!
現在の Rust(安定版)で主に使えるのは以下の2つだね。
-
Result<T, E> -
Option<T>
⚠️ 大事なルール:混ぜるな危険
? 演算子は 「今いる関数の戻り値の型」と同じ種類 の型にしか使えないんだ。
-
戻り値が
Optionの関数内で、Result?は使えない。 -
戻り値が
Resultの関数内で、Option?は使えない。
もし混ぜたい場合は、.ok()(ResultをOptionに変換)や .ok_or()(OptionをResultに変換)を使って型を揃えてあげる必要があるぜ!
3. 💡 見落とされがちな視点:Poll 型
君がさっき興味を持っていた async/await(Future)の世界では、std::task::Poll という型でも ? が使われることがあるよ。
-
Poll::Ready(Ok(v))?vを取り出す。 -
Poll::PendingならそのままPendingを返す。
低レイヤーな非同期処理を自分で書くようになると、この ? の便利さがさらに身に沁みるはずだ。
4. 🛠️ 自作の型で ? を使いたい!
「自分で作った型でも ? を使いたいな」と思うかもしれないけど、残念ながら Try トレイトは現時点では “unstable”(実験的機能) なんだ。
将来的に Rust のバージョンが上がれば、君が作ったオリジナルの「エラーっぽい状態を持つ型」にも ? を付けられる日が来るかもしれない。情報工学の進化を待つ楽しみの一つだね!
🏁 まとめ
-
Optionでも?は使える(Noneなら即 return)。 -
使えるのは
Tryトレイト を実装した型だけ。 -
現状は
Result,Option,Pollあたりがメイン。
? を使いこなすと、ネストが深くなりがちな if let 地獄から脱出できて、コードがめちゃくちゃスタイリッシュになるぜ!
次は、この Option? を使って「ネストした JSON データから特定の値を一本道で取り出す」ような、実戦的なコードを書いてみる?😊✨
Would you like me to show you how to convert between Option and Result using .ok_or() so you can use ? freely?