Refutability в сопоставлении шаблонов Rust

RustRustBeginner
Практиковаться сейчас

This tutorial is from open-source community. Access the source code

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

Добро пожаловать в Refutability: Whether a Pattern Might Fail to Match. Эта лабораторная работа является частью Rust Book. Вы можете практиковать свои навыки Rust в LabEx.

В этой лабораторной работе мы узнаем о концепции refutability в шаблонах и о том, как она влияет на процесс сопоставления в Rust, включая различие между refutable и irrefutable шаблонами и о том, как правильно их использовать в различных конструкциях, таких как let-операторы и if let-выражения.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") subgraph Lab Skills rust/variable_declarations -.-> lab-100445{{"Refutability в сопоставлении шаблонов Rust"}} rust/expressions_statements -.-> lab-100445{{"Refutability в сопоставлении шаблонов Rust"}} end

Refutability: Whether a Pattern Might Fail to Match

Шаблоны бывают двух типов: refutable и irrefutable. Шаблоны, которые будут совпадать для любого возможного переданного значения, являются irrefutable. Например, x в выражении let x = 5;, потому что x совпадает с любым значением и, следовательно, не может не совпадать. Шаблоны, которые могут не совпадать для некоторых возможных значений, являются refutable. Например, Some(x) в выражении if let Some(x) = a_value, потому что если значение в переменной a_value равно None вместо Some, шаблон Some(x) не совпадет.

Параметры функций, let-операторы и циклы for могут принимать только irrefutable шаблоны, потому что программа не может сделать ничего полезного, когда значения не совпадают. Выражения if let и while let могут принимать refutable и irrefutable шаблоны, но компилятор предупреждает о использовании irrefutable шаблонов, потому что по определению они предназначены для обработки возможной ошибки: функциональность условного оператора заключается в том, чтобы выполняться по-разному в зависимости от успеха или неудачи.

В общем, вам не нужно беспокоиться о различии между refutable и irrefutable шаблонами; однако, вам нужно быть знакомым с концепцией refutability, чтобы знать, как реагировать, когда вы видите ее в сообщении об ошибке. В таких случаях вам нужно изменить либо шаблон, либо конструкцию, в которой вы используете шаблон, в зависимости от предполагаемого поведения кода.

Рассмотрим пример того, что происходит, когда мы пытаемся использовать refutable шаблон, где Rust требует irrefutable шаблона, и наоборот. Listing 18-8 показывает let-оператор, но для шаблона мы указали Some(x), refutable шаблон. Как вы могли ожидать, этот код не скомпилируется.

let Some(x) = some_option_value;

Listing 18-8: Попытка использовать refutable шаблон с let

Если some_option_value было бы значением None, оно не совпадало бы с шаблоном Some(x), что означает, что шаблон refutable. Однако, let-оператор может принимать только irrefutable шаблон, потому что код не может сделать ничего полезного с значением None. При компиляции Rust сообщит, что мы пытаемся использовать refutable шаблон, где требуется irrefutable шаблон:

error[E0005]: refutable pattern in local binding: `None` not covered
   --> src/main.rs:3:9
    |
3   |     let Some(x) = some_option_value;
    |         ^^^^^^^ pattern `None` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or
an `enum` with only one variant
    = note: for more information, visit
https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `Option<i32>`
help: you might want to use `if let` to ignore the variant that isn't matched
    |
3   |     let x = if let Some(x) = some_option_value { x } else { todo!() };
    |     ++++++++++                                 ++++++++++++++++++++++

Поскольку мы не охватили (и не могли охватить!) все допустимые значения шаблоном Some(x), Rust правильно генерирует ошибку компиляции.

Если у нас есть refutable шаблон, где требуется irrefutable шаблон, мы можем исправить это, изменив код, который использует шаблон: вместо let мы можем использовать if let. Затем, если шаблон не совпадает, код просто пропустит код в фигурных скобках, обеспечив тем самым способность продолжить выполнение валидно. Listing 18-9 показывает, как исправить код из Listing 18-8.

if let Some(x) = some_option_value {
    println!("{x}");
}

Listing 18-9: Использование if let и блока с refutable шаблонами вместо let

Мы дали код выход! Этот код полностью валиден, хотя это означает, что мы не можем использовать irrefutable шаблон без получения ошибки. Если мы передадим if let шаблон, который всегда совпадает, например, x, как показано в Listing 18-10, компилятор выдаст предупреждение.

if let x = 5 {
    println!("{x}");
};

Listing 18-10: Попытка использовать irrefutable шаблон с if let

Rust сообщает, что использовать if let с irrefutable шаблоном не имеет смысла:

warning: irrefutable `if let` pattern
 --> src/main.rs:2:8
  |
2 |     if let x = 5 {
  |        ^^^^^^^^^
  |
  = note: `#[warn(irrefutable_let_patterns)]` on by default
  = note: this pattern will always match, so the `if let` is
useless
  = help: consider replacing the `if let` with a `let`

По этой причине ветви match должны использовать refutable шаблоны, за исключением последней ветви, которая должна совпадать с любыми оставшимися значениями с помощью irrefutable шаблона. Rust позволяет использовать irrefutable шаблон в match с только одной ветвью, но этот синтаксис не особо полезен и может быть заменен на более простой let-оператор.

Теперь, когда вы знаете, где использовать шаблоны и разницу между refutable и irrefutable шаблонами, давайте рассмотрим весь синтаксис, который мы можем использовать для создания шаблонов.

Резюме

Поздравляем! Вы завершили лабораторную работу Refutability: Whether a Pattern Might Fail to Match. Вы можете практиковаться в других лабораторных работах в LabEx, чтобы улучшить свои навыки.