見出し画像

Claude Codeを使いこなすためのRust入門【第2回】つまずきやすいポイントOption・Result・async

はじめに:今日のテーマは「もしも」への備え

 前回は、Rust でいちばん大事な「所有権」と「借用」をお話ししました。「持ち主はひとり」「貸すときは `&`」でした。

 さて、今回のテーマはこちらです。

  • `Option`(オプション)

  • `Result`(リザルト)

  • `async`(エイシンク)/ `await`(アウェイト)

 これらは、「もしも、うまくいかなかったらどうする?」という「備え」の仕組みです。

 そして、ここは Claude Code が作るプログラムの中で特にわかりにくい場所でもあります。だからこそ、あなたが少しだけ知っておくと、開発がぐっと安定します。


なぜこの知識が必要なのか

 Claude Code は賢いですが、ときどき「とりあえず動けばいい」というようなコードを書きます。

 その代表が、これから出てくる `unwrap()`(アンラップ)というものです。
これは便利な一方で、ある条件がそろうとアプリが突然クラッシュ(強制終了)する原因になります。

 つまり、あなたがこの仕組みを知らないと、「テストでは動いたのに、本番で急に落ちる」というトラブルに気づけません。

 逆に言えば、ポイントを知っているだけで、「ここ、危ない書き方になってない?」と Claude Code にひとこと言えるようになります。

 それだけで、あなたのアプリはぐっと壊れにくくなります。


基本概念(1):Option 〜「あるかも、ないかも」を表す箱〜

 まず `Option` です。これは、「中身があるかもしれないし、ないかもしれない箱」だと思ってください。

 身近な例で言うと、郵便受けです。朝、郵便受けをのぞくと、手紙が入っていることもあれば、空っぽのこともありますよね。

 Rust では、この「あるかないか分からない状態」を、`Option` という箱で表します。中身は2種類です。

  • `Some(値)` … 中身がある(手紙が入っている)

  • `None` … 中身がない(空っぽ)

 コードで見てみましょう。

fn find_user(id: i32) -> Option<String> {
    if id == 1 {
        Some(String::from("田中さん")) // 見つかった
    } else {
        None // 見つからなかった
    }
}

 このコードは「IDで利用者を探す」関数です。ID が `1` なら「田中さん」が見つかったので `Some` で包んで返します。それ以外なら、見つからなかったので `None` を返します。

 ポイントは、「見つからないかもしれない」ことを、型(かた)で正直に表していることです。

 Rust は「もしかしたら空っぽかもよ」と最初から教えてくれるので、うっかり空っぽのものを使ってアプリが壊れる、という事故を防げるのです。


基本概念(2):Result 〜「成功か、失敗か」を表す箱〜

 次に `Result` です。`Option` が「あるか、ないか」だったのに対し、
`Result` は「成功したか、失敗したかを表す箱」です。

 例えるなら、試験の結果通知です。封筒を開けると「合格」か「不合格」、どちらかが入っています。

 `Result` の中身も2種類です。

  • `Ok(値)` … 成功(合格。中に成功した結果が入っている)

  • `Err(理由)` … 失敗(不合格。中に失敗の理由が入っている)

fn divide(a: i32, b: i32) -> Result<i32, String> {
    if b == 0 {
        Err(String::from("0では割れません")) // 失敗
    } else {
        Ok(a / b) // 成功
    }
}

 このコードは「割り算をする」関数です。割る数が `0` だと計算できないので、`Err` に理由を入れて返します。それ以外なら、ちゃんと計算して `Ok` で結果を包んで返します。

 `Option` との違いは、失敗したときに「なぜ失敗したか」も一緒に渡せることです。ファイルの読み込みやネット通信など、「失敗の理由を知りたい」場面で大活躍します。反対に、失敗することが普通で、特に理由を知る必要がないような場合は、`Option`を用います。


ここが要注意:unwrap と panic

 さて、いよいよ Claude Code が間違えやすいポイントです。

 `Option` や `Result` は箱に包まれているので、中身を取り出すにはひと手間かかります。

 その「ひと手間」を一気に省略する魔法が、`unwrap()`(アンラップ)です。名前のとおり「包み(wrap)をむく(un)」という意味です。

let result = divide(10, 0);
let answer = result.unwrap(); // 危険!

 この `unwrap()` は、中身があれば取り出してくれます。便利です。

 でも、もし中身が `None` や `Err`(つまり失敗)だったら?

 そのとき Rust は、なんとアプリを強制終了させます。この強制終了のことをpanic(パニック)と呼びます。

 つまり `unwrap()` は、「中身が必ずあると信じて、もし無かったらアプリごと爆発する」という、かなり強気な書き方なのです。

 Claude Code は、手早く動くコードを作ろうとして、この `unwrap()` をあちこちに置いてしまうことがあります。お試しなら問題ないかもしれませんが、本番のアプリでは多用しないように注意しましょう。


安全な取り出し方:match

 では、どうすれば安全なのでしょうか。

 おすすめは `match`(マッチ)という仕組みです。「もし中身がこうなら、こうする」を、ていねいに場合分けします。

let result = divide(10, 0);

match result {
    Ok(answer) => println!("答えは {}", answer), // 成功したとき
    Err(reason) => println!("エラー: {}", reason), // 失敗したとき
}

 このコードは、割り算の結果を場合分けして処理しています。

・`Ok` だったら(成功)、答えを表示します。
・`Err` だったら(失敗)、その理由を表示します。

 `unwrap()` と違って、失敗してもアプリは爆発しません。ちゃんと「エラーが出ましたよ」と教えてくれるだけです。これが、人にやさしいエラー処理です。


便利な近道:? 演算子

 毎回 `match` を書くのは、正直ちょっと面倒です。そこで Rust には、`?`(クエスチョンマーク)という便利な近道があります。

fn calc() -> Result<i32, String> {
    let answer = divide(10, 2)?; // 成功なら中身を取り出す
    Ok(answer + 1)
}

 `divide(10, 2)?` の最後についている `?` がポイントです。この `?` は、こう動きます。

  • 成功(`Ok`)なら → 中身を取り出して、次に進む

  • 失敗(`Err`)なら → そこで処理をやめて、エラーを呼び出し元に返す

 つまり `?` は、「成功したら進む、失敗したら安全に引き返す」という、かしこい近道なのです。

 `unwrap()` のようにアプリを爆発させず、失敗をきちんと外へ伝えてくれます。Claude Code のコードに `?` が出てきたら、「お、安全な書き方だな」と思ってOKです。


基本概念(3):async / await 〜「待ち時間」を上手に使う仕組み〜

 最後は `async`(アシンク)`await`(アウェイト)です。

 これは、「時間のかかる作業を、待っている間に他のこともやる」仕組みです。

 カフェで例えましょう。

 あなたがコーヒーを注文します。
 注文を取る店員さんは、あなたのコーヒーができるのをただ突っ立って待ったりしません。
 その間に、次のお客さんの注文を取りますよね。

 `async` は、まさにこれです。ネット通信やファイル読み込みなど「待ち時間が発生する作業」のとき、待っている間にパソコンが他の仕事を進められるようにします。

async fn get_data() -> String {
    let data = fetch_from_web().await; // ここで待つ
    data
}

 `async fn` は「これは待ち時間がある関数ですよ」という宣言です。

 そして `.await` が「ここで待ち時間が発生します」という合図です。ただし、ただ突っ立って待つのではなく、待っている間は他の処理に道をゆずります。

 初心者のうちは、ここまで理解できれば十分です。「`async` と `await` はセットで、待ち時間を上手に使うためのもの」と覚えておけば大丈夫です。


Claude Codeがasyncで間違えやすいこと

 `async` まわりは、Claude Code でもエラーが出やすい場所です。よくあるのは、こんなエラーです。

  • `await` の付け忘れ

  • `async` ではない普通の関数の中で `.await` を使ってしまう

  • 動かすための土台(ランタイムと呼ばれます)の設定が足りない

 エラーメッセージに `await`、`async`、`Future` といった単語が出てきたら、「これは待ち時間まわりの話だな」と気づければ十分です。

 細かい設定は、Claude Code にお願いすれば直してくれます。


AIへの指示例

 では、今回も大事な「AI への頼み方」です。

(1) unwrap を見つけたとき

悪い例

エラーが出ないようにして

良い例

このコードに `unwrap()` が使われています。
失敗したときにアプリが落ちないよう、`match` か `?` を使った
安全なエラー処理に書き換えてください。

(2) エラー処理を頼むとき

悪い例

ちゃんとエラー処理して

良い例

この関数で失敗が起きる可能性がある箇所を教えてください。
その上で、`Result` 型を使い、失敗の理由が分かるように
エラー処理を追加してください。

(3)async で困ったとき

悪い例

動かない、直して

良い例

`await` まわりでエラーが出ています。
どこで待ち時間が発生しているのかを説明した上で、
正しく `await` を付けて修正してください。

 共通するコツは、前回と同じです。エラーをそのまま貼る、専門用語を使う、直す方向を示す。この3つで、Claude Code の精度は大きく変わります。


まとめ

 今回は、Claude Code が間違えやすい3つのポイントを見てきました。

  • Option:中身があるかも、ないかもの箱(`Some` / `None`)

  • Result:成功か失敗かの箱(`Ok` / `Err`)

  • unwrap:便利だけど、失敗するとアプリが爆発(panic)する危険な近道

  • match:ていねいに場合分けする、安全な取り出し方

  • ? 演算子:成功なら進む、失敗なら安全に引き返すかしこい近道

  • async / await:待ち時間を上手に使う仕組み。セットで覚える

 全部を完璧に理解する必要はありません。大事なのは、「あ、ここ `unwrap` 使ってるな、危ないかも」、「これは待ち時間まわりの話だな」と気づけること

 そして、Claude Code に「安全なエラー処理に直して」とお願いできることです。

 Rust の「もしもへの備え」は、最初は回りくどく感じます。でもそれは、あなたのアプリを守るための優しさです。

 仕組みを少し知っているだけで、その優しさを味方にできます。「Claude Code となら、壊れにくいアプリも作れそう」。そう思っていただけたら、うれしいです。

 次回はいよいよ最終回。`Cargo` や依存ライブラリ、そしてセキュリティといった「実際に開発を進めるための道具」についてお話しします。


【第1回】所有権・借用を理解すれば世界が変わる

【第3回】Cargo・依存ライブラリ・セキュリティ

 今回の連載について、ChatGPT(5.5)に全体構成とファクトチェックと表紙画像生成を、Claude Cowork(Opus 4.8)に原稿作成を、それぞれ担当してもらいました。最後に、私が加筆・修正しています。

いいなと思ったら応援しよう!