FABRKNT
Reth Fundamentals — Alloy で動かす最初の一歩
Alloyを使う
レッスン 3 / 11·CONTENT12 分25 XP
コース
Reth Fundamentals — Alloy で動かす最初の一歩
レッスンの役割
CONTENT
順序
3 / 11

レッスン3 — Rust:Result・Option・? 演算子

問い

Rust にはエラーを返す関数が大量にある。それらをすべて手動でアンラップすると、コードが try/catch だらけになる。Rust は ? 演算子で「エラーなら早期 return、成功なら値を取り出す」を 1 文字で書ける。Alloy のコードを読むときに ? が至る所に出てくる理由を理解する。

原理(最小モデル)

  • Result<T, E>. 成功 = Ok(T)、失敗 = Err(E)、関数の戻り値型として「失敗しうる」を型で表現。
  • Option<T>. 値あり = Some(T)、なし = None、null の代わり、unwrap せずに済む。
  • ? 演算子. result? = match result { Ok(v) => v, Err(e) => return Err(e.into()) } の糖衣、エラーは呼び出し元へ自動伝播。
  • .await? 組み合わせ. async 関数で頻出、.await で Future 完了待ち + ? でエラー伝播 = 同期的に書ける async コード。
  • unwrap() vs ?. unwrap() = エラーで panic(学習 / プロトタイプ)、? = エラーを呼び出し元へ伝播(本番コード)。

具体例 + ステップで組み立てる

Rust:Result・Option・? 演算子

Alloyコードでは、ほぼすべての行に .await?.parse()? が出る。これは Rustのエラーハンドリング 構文である。

1. なぜ例外がないのか

Rustに try/catch(例外)はない。代わりに 値としてエラーを返す 設計を取る。

  • 関数は「成功」か「失敗」を Result<T, E> で返す
  • 値があるかないかは Option<T> で返す

これらは enum(列挙型)である。

enum Result<T, E> {
    Ok(T),
    Err(E),
}

enum Option<T> {
    Some(T),
    None,
}

2. Option:あるか、ないか

let v: Vec<i32> = vec![1, 2, 3];
let first: Option<&i32> = v.first();   // Some(&1)
let empty: Vec<i32> = vec![];
let none: Option<&i32> = empty.first();// None

match first {
    Some(n) => println!("got {}", n),
    None => println!("empty"),
}

3. Result:成功か、エラーか

fn parse_int(s: &str) -> Result<i32, std::num::ParseIntError> {
    s.parse::<i32>()
}

match parse_int("42") {
    Ok(n) => println!("got {}", n),
    Err(e) => println!("oops: {}", e),
}

4. ? 演算子:エラー伝播の魔法

?「エラーなら今すぐ関数からreturn、成功なら中身を取り出す」 という意味だ。

fn parse_two(a: &str, b: &str) -> Result<(i32, i32), std::num::ParseIntError> {
    let x = a.parse::<i32>()?;   // 失敗したら早期リターン
    let y = b.parse::<i32>()?;   // 失敗したら早期リターン
    Ok((x, y))
}

? がない場合、毎回 match を書く必要があり、同じ意味のコードが大きく長くなる。

5. Result<(), Box<dyn Error>>eyre::Result<()>

main関数の戻り値でよく見るやつです:

意味
Result<(), Box<dyn std::error::Error>>標準ライブラリのみ(やや冗長)
eyre::Result<()>eyre クレートの便利版(推奨)

eyre は「読みやすいエラー出力」と「多様なエラー型の統合」が特徴である。Alloyコードでは eyre::Result<()> が事実上の標準になる。

6. unwrap()expect()

学習段階でよく使う「エラーを無視する」方法。本番では使わないでください(パニックします)。

let n: i32 = "42".parse().unwrap();          // 失敗ならパニック
let n: i32 = "42".parse().expect("not an int"); // メッセージ付きパニック

7. これからAlloyで見るパターン

async fn main() -> eyre::Result<()> {
    let provider = ProviderBuilder::new()
        .connect_http("https://eth.llamarpc.com".parse()?);  // ?: parse失敗→return
    let block = provider.get_block_number().await?;          // ?: RPC失敗→return
    Ok(())
}

ほぼすべての行で ? が活躍する。「成功ならそのまま、失敗なら呼び出し元へ返す」 と覚えればよい。

次のレッスンでこれを実際のProvider接続コードに使う。

まとめ(3行)

  • Result<T, E> 成功 / 失敗 + Option<T> 値あり / なし = Rust のエラー / 不在表現、type system が「失敗しうる」を強制。
  • ? 演算子 = エラー時に早期 return、.await? で async + エラー伝播、try/catch の地獄を 1 文字で避ける。
  • unwrap() は学習用 / ? は本番、次は Provider でノードへ接続。