Réfutabilité dans la correspondance de motifs en Rust

RustRustBeginner
Pratiquer maintenant

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

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Bienvenue dans Refutabilité : La possibilité qu'un motif ne corresponde pas. Ce laboratoire est une partie du Rust Book. Vous pouvez pratiquer vos compétences Rust dans LabEx.

Dans ce laboratoire, nous allons découvrir le concept de réfutabilité dans les motifs et comment cela affecte le processus de correspondance en Rust, y compris la distinction entre les motifs réfutables et irréfutables et la manière de les utiliser correctement dans différents constructs tels que les instructions let et les expressions if let.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") subgraph Lab Skills rust/variable_declarations -.-> lab-100445{{"Réfutabilité dans la correspondance de motifs en Rust"}} rust/expressions_statements -.-> lab-100445{{"Réfutabilité dans la correspondance de motifs en Rust"}} end

Refutabilité : La possibilité qu'un motif ne corresponde pas

Les motifs se présentent sous deux formes : réfutables et irréfutables. Les motifs qui correspondent à n'importe quelle valeur possible passée sont irréfutables. Un exemple serait x dans l'énoncé let x = 5; car x correspond à tout et ne peut donc pas échouer à correspondre. Les motifs qui peuvent échouer à correspondre pour certaines valeurs possibles sont réfutables. Un exemple serait Some(x) dans l'expression if let Some(x) = a_value car si la valeur dans la variable a_value est None plutôt que Some, le motif Some(x) ne correspondra pas.

Les paramètres de fonction, les instructions let et les boucles for ne peuvent accepter que des motifs irréfutables car le programme ne peut rien faire de significatif lorsque les valeurs ne correspondent pas. Les expressions if let et while let acceptent des motifs réfutables et irréfutables, mais le compilateur avertit contre les motifs irréfutables car, par définition, ils sont destinés à gérer les échecs possibles : la fonctionnalité d'une condition est dans sa capacité à se comporter différemment selon le succès ou l'échec.

En général, vous n'avez pas à vous soucier de la distinction entre les motifs réfutables et irréfutables ; cependant, vous devez être familier du concept de réfutabilité pour pouvoir répondre lorsqu'il apparaît dans un message d'erreur. Dans ces cas, vous devrez modifier soit le motif, soit la construction dans laquelle vous utilisez le motif, selon le comportement souhaité du code.

Regardons un exemple de ce qui se passe lorsque nous essayons d'utiliser un motif réfuté où Rust exige un motif irréfuté et vice versa. La liste 18-8 montre une instruction let, mais pour le motif, nous avons spécifié Some(x), un motif réfuté. Comme vous le devriez imaginer, ce code ne compilera pas.

let Some(x) = some_option_value;

Liste 18-8 : Tentative d'utilisation d'un motif réfuté avec let

Si some_option_value était une valeur None, elle ne correspondrait pas au motif Some(x), ce qui signifie que le motif est réfuté. Cependant, l'instruction let ne peut accepter que des motifs irréfutables car il n'y a rien de valide que le code puisse faire avec une valeur None. Au moment de la compilation, Rust signalera qu'il y a eu une erreur car nous avons essayé d'utiliser un motif réfuté où un motif irréfuté était requis :

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

Comme nous n'avons pas couvert (et ne pouvions pas couvrir!) toutes les valeurs valides avec le motif Some(x), Rust produit légitimement une erreur de compilation.

Si nous avons un motif réfuté où un motif irréfuté est nécessaire, nous pouvons le corriger en changeant le code qui utilise le motif : au lieu d'utiliser let, nous pouvons utiliser if let. Ensuite, si le motif ne correspond pas, le code saute simplement le code entre les accolades, lui donnant ainsi un moyen de continuer correctement. La liste 18-9 montre comment corriger le code de la liste 18-8.

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

Liste 18-9 : Utilisation de if let et d'un bloc avec des motifs réfutés au lieu de let

Nous avons trouvé une solution! Ce code est parfaitement valide, bien que cela signifie que nous ne pouvons pas utiliser un motif irréfuté sans recevoir une erreur. Si nous donnons à if let un motif qui correspondra toujours, tel que x, comme montré dans la liste 18-10, le compilateur donnera un avertissement.

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

Liste 18-10 : Tentative d'utilisation d'un motif irréfuté avec if let

Rust signale qu'il n'a pas de sens d'utiliser if let avec un motif irréfuté :

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`

Pour cette raison, les branches de correspondance doivent utiliser des motifs réfutés, sauf pour la dernière branche, qui devrait correspondre à toutes les valeurs restantes avec un motif irréfuté. Rust nous permet d'utiliser un motif irréfuté dans une correspondance avec une seule branche, mais cette syntaxe n'est pas particulièrement utile et pourrait être remplacée par une instruction let plus simple.

Maintenant que vous savez où utiliser les motifs et la différence entre les motifs réfutés et irréfutés, couvrons toute la syntaxe que nous pouvons utiliser pour créer des motifs.

Sommaire

Félicitations! Vous avez terminé le laboratoire Refutabilité : La possibilité qu'un motif ne corresponde pas. Vous pouvez pratiquer d'autres laboratoires dans LabEx pour améliorer vos compétences.