0Pricing
Learn Rust Coding · Урок

Мощное сопоставление с образцом

Освойте выражения `match` и другие конструкции сопоставления с образцом для краткой и исчерпывающей обработки вариантов данных.

«Мощное сопоставление с образцом» — бесплатный урок Learn Rust Coding на CoddyKit. Это урок 3 из 3. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Learn Rust Coding, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Learn Rust Coding содержит 3 уроков всего.

Части этого урока еще не переведены и отображаются на английском.

Unleashing Pattern Matching

Welcome to the world of pattern matching in Rust! This powerful feature allows you to control program flow based on the structure of data.

Instead of just checking equality, you can deconstruct values, extract components, and execute specific code for different data shapes.

  • It's like a super-powered if/else or switch statement.
  • Ensures exhaustiveness: you must handle all possible patterns.
  • Makes code more readable and robust.

The `match` Expression Basics

The core of pattern matching is the match expression. It takes a value and compares it against a series of patterns. The first pattern that matches wins!

Each 'arm' of a match expression consists of a pattern and the code to execute if that pattern matches.

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!"),
  }
}

Matching Literals and Ranges

You can match against specific literal values (numbers, characters, booleans) or define ranges using ..=. The | operator allows matching multiple patterns with a single arm.

Remember, patterns are checked in order, and the first match is used.

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"),
  }
}

Destructuring Structs

Pattern matching really shines when destructuring complex data types like structs. You can extract individual fields directly into variables within the match arm.

This makes accessing struct data clean and concise, especially when matching specific field values.

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),
  }
}

Destructuring Enums with Data

Enums in Rust can hold associated data. Pattern matching is the primary way to extract this data from an enum variant.

You can destructure the data directly into new variables, making it easy to work with the content of each variant.

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!")));
}

The Wildcard Pattern `_`

The special _ (underscore) pattern acts as a catch-all. It matches any value and does not bind to that value.

It's useful when you need to cover all possibilities for exhaustiveness but don't care about the specific value that matches a particular arm.

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` for Single Patterns

Sometimes, you only care about matching one specific pattern and want to ignore all others. For these cases, if let is a more concise alternative to a full match expression.

It essentially says: "if this pattern matches, then do this; otherwise, do nothing (or execute an optional else block).".

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` for Conditional Loops

Similar to if let, while let allows you to loop as long as a pattern continues to match.

This is extremely useful for processing items from collections like Vecs where you want to continue until there are no more matching elements (e.g., until pop() returns 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 Guards: Adding Conditions

You can add an additional if condition, called a match guard, to a match arm. The pattern must match AND the guard condition must be true for that arm to execute.

This allows for more fine-grained control within a pattern, without needing to create more enum variants.

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"),
  }
}

Pattern Matching Challenge

Consider the following Rust code snippet. Which of the following statements about the match expression and its output are TRUE?

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));
}

Recap: Mastering Patterns

You've explored the incredible power of pattern matching in Rust! It's a fundamental concept for writing clear, concise, and safe code.

  • match expressions provide exhaustive control flow based on data structure.
  • You can match literals, ranges, and use wildcards (_).
  • Destructuring allows extracting values from structs and enums directly.
  • if let and while let offer concise ways to match single patterns.
  • Match guards add conditional logic to match arms.

Keep practicing these patterns; they're essential for idiomatic Rust!

Часто задаваемые вопросы

Урок «Мощное сопоставление с образцом» бесплатный?

Да — полный текст урока «Мощное сопоставление с образцом» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Learn Rust Coding, подпишись на CoddyKit PRO. Курс Learn Rust Coding содержит 3 уроков всего.

Чему я научусь в уроке «Мощное сопоставление с образцом»?

Освойте выражения `match` и другие конструкции сопоставления с образцом для краткой и исчерпывающей обработки вариантов данных. Ты практикуешь Learn Rust Coding с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Learn Rust Coding?

Предыдущий опыт не требуется. Learn Rust Coding на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 3.

Сколько времени занимает урок «Мощное сопоставление с образцом»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Learn Rust Coding?

Да. Каждый урок Learn Rust Coding включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Определение и использование структур
  2. Перечисления для пользовательских типов
  3. Мощное сопоставление с образцом
← Назад к Learn Rust Coding