0Pricing
Learn Rust Coding · レッスン

強力なパターンマッチング

データのバリアントを簡潔かつ漏れなく処理するために、`match`式などのパターンマッチング構文を使いこなします。

「強力なパターンマッチング」はCoddyKit上の無料Learn Rust Codingレッスンです。 これはレッスン3/3です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLearn Rust Coding学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Learn Rust Codingコースには全3レッスンが含まれています。

パターンマッチングを活用する

Rustのパターンマッチングの世界へようこそ。この強力な機能を使うと、データの構造に基づいてプログラムの流れを制御できます。

単に等しいかどうかを確認するだけでなく、値を分解して構成要素を取り出し、データの形ごとに異なるコードを実行できます。

  • 強力になった if/else や switch 文のようなものです。
  • 網羅性が保証されるため、すべての可能なパターンを処理する必要があります。
  • コードが読みやすく、堅牢になります。

`match` 式の基本

パターンマッチングの中心となるのが match 式です。値を受け取り、一連のパターンと比較します。最初に一致したパターンが選ばれます。

match 式の各「アーム」は、パターンと、そのパターンが一致した場合に実行するコードで構成されます。

enum Direction {
  North,
  East,
  South,
  West,
}

fn main() {
  let my_direction = Direction::North;

  match my_direction {
    Direction::North => println!("Going up!"),
    Direction::East => println!("Going right!"),
    Direction::South => println!("Going down!"),
    Direction::West => println!("Going left!"),
  }
}

リテラルと範囲のマッチング

特定のリテラル値(数値、文字、真偽値)に対してマッチングしたり、..= を使って範囲を定義したりできます。| 演算子を使うと、1つのアームで複数のパターンにマッチングできます。

パターンは順番に確認され、最初に一致したものが使われることを覚えておきましょう。

fn main() {
  let x = 7;

  match x {
    1 => println!("It's one!"),
    2 | 3 => println!("It's two or three!"),
    4..=8 => println!("It's between four and eight!"),
    _ => println!("It's something else!"), // Catch-all
  }

  let character = 'b';
  match character {
    'a'..='e' => println!("Early letter"),
    _ => println!("Other letter"),
  }
}

構造体の分解

構造体のような複雑なデータ型を分解すると、パターンマッチングの真価が発揮されます。match のアーム内で、個々のフィールドを直接変数に取り出せます。

特定のフィールド値にマッチングする場合でも、構造体のデータにすっきり簡潔にアクセスできます。

struct Point {
  x: i32,
  y: i32,
}

fn main() {
  let p = Point { x: 0, y: 7 };

  match p {
    Point { x, y: 0 } => println!("On the X axis at {}", x),
    Point { x: 0, y } => println!("On the Y axis at {}", y),
    Point { x, y } => println!("Not on an axis: ({}, {})", x, y),
  }
}

データを持つ列挙型の分解

Rustの列挙型には関連データを持たせることができます。列挙型のバリアントからこのデータを取り出す主な方法が、パターンマッチングです。

データを直接新しい変数に分解できるため、それぞれのバリアントの内容を簡単に扱えます。

enum Message {
  Quit,
  Move { x: i32, y: i32 },
  Write(String),
  ChangeColor(i32, i32, i32),
}

fn process_message(msg: Message) {
  match msg {
    Message::Quit => println!("Quit message."),
    Message::Move { x, y } => {
      println!("Move to x: {}, y: {}", x, y);
    }
    Message::Write(text) => println!("Text message: {}", text),
    Message::ChangeColor(r, g, b) => {
      println!("Color: R:{}, G:{}, B:{}", r, g, b);
    }
  }
}

fn main() {
  process_message(Message::Move { x: 10, y: 20 });
  process_message(Message::Write(String::from("Hello!")));
}

ワイルドカードパターン `_`

特殊な _(アンダースコア)パターンはすべてにマッチするパターンとして機能します。どの値にもマッチしますが、その値を束縛しません。

網羅性を満たすためにすべての可能性をカバーする必要がある一方で、特定のアームに一致した値自体には関心がない場合に便利です。

fn main() {
  let some_value = Some(5);
  let absent_value: Option<i32> = None;

  match some_value {
    Some(x) => println!("Got a value: {}", x),
    _ => println!("Something else!"), // Matches None too
  }

  match absent_value {
    Some(x) => println!("Got a value: {}", x),
    _ => println!("No value here!"),
  }
}

単一パターン向けの `if let`

特定の1つのパターンだけに関心があり、それ以外は無視したい場合があります。このようなとき、if let は完全な match 式より簡潔な代替手段になります。

これは基本的に、「このパターンに一致したらこれを実行し、それ以外の場合は何もしない(または任意の else ブロックを実行する)」という意味です。

fn main() {
  let config_max = Some(3u8);
  let none_value: Option<u8> = None;

  if let Some(max) = config_max {
    println!("Max configured to be: {}", max);
  }

  if let Some(val) = none_value {
    println!("This won't print: {}", val);
  } else {
    println!("No value found!");
  }
}

条件付きループ向けの `while let`

if let と同様に、while let を使うと、パターンが一致し続ける間ループできます。

これは、Vec のようなコレクションから項目を処理するときに非常に便利です。一致する要素がなくなるまで(たとえば pop() が None を返すまで)処理を続けられます。

fn main() {
  let mut stack = vec![1, 2, 3];

  while let Some(top) = stack.pop() {
    println!("Popped: {}", top);
  }

  println!("Stack is empty now.");
}

マッチガード:条件を追加する

match のアームには、マッチガードと呼ばれる追加の if 条件を指定できます。そのアームを実行するには、パターンが一致し、かつガード条件が真でなければなりません。

これにより、列挙型のバリアントをさらに増やさなくても、パターン内でより細かく制御できます。

fn main() {
  let num = Some(4);

  match num {
    Some(x) if x % 2 == 0 => println!("Even number: {}", x),
    Some(x) if x < 5 => println!("Small odd number: {}", x),
    Some(x) => println!("Any other number: {}", x),
    None => println!("No number"),
  }
}

パターンマッチングのチャレンジ

次のRustコードを見てください。match 式とその出力について、次の記述のうち正しいものはどれでしょうか。

enum Status {
  Loading,
  Success(u32),
  Error(String),
}

fn process_status(s: Status) {
  match s {
    Status::Success(code) if code > 200 => println!("Success with high code: {}", code),
    Status::Success(code) => println!("Success with code: {}", code),
    Status::Error(msg) => println!("Failed: {}", msg),
    _ => println!("Status unknown or loading..."),
  }
}

fn main() {
  process_status(Status::Success(201));
  process_status(Status::Error(String::from("Network issue")));
  process_status(Status::Loading);
  process_status(Status::Success(200));
}

振り返り:パターンを使いこなす

Rustのパターンマッチングが持つ素晴らしい力を学びました。これは、明確で簡潔かつ安全なコードを書くための基本概念です。

  • match 式は、データ構造に基づく網羅的なフロー制御を提供します。
  • リテラルや範囲、ワイルドカード(_)を使ってマッチングできます。
  • 分解により、構造体や列挙型から値を直接取り出せます。
  • if let と while let を使うと、単一パターンに対して簡潔にマッチングできます。
  • マッチガードを使うと、match のアームに条件ロジックを追加できます。

これらのパターンを練習し続けましょう。Rustらしいコードを書くために欠かせないものです。

よくある質問

「強力なパターンマッチング」レッスンは無料ですか?

はい。「強力なパターンマッチング」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Learn Rust Codingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Learn Rust Codingコースには全3レッスンが含まれています。

「強力なパターンマッチング」で何を学びますか?

データのバリアントを簡潔かつ漏れなく処理するために、`match`式などのパターンマッチング構文を使いこなします。 ブラウザで直接実行するハンズオンコードでLearn Rust Codingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Learn Rust Codingを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのLearn Rust Codingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/3です。

「強力なパターンマッチング」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このLearn Rust Codingレッスンでコードを書いて実行できますか?

はい。すべてのLearn Rust Codingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 構造体の定義と利用
  2. カスタム型のための列挙型
  3. 強力なパターンマッチング
← Learn Rust Codingに戻る