Match en Rust
match compare une valeur à une liste de motifs (patterns) et exécute le code de celui qui correspond. Si vous avez déjà utilisé une instruction switch, voyez-le comme une version bien plus puissante. Et si vous n’en avez jamais utilisé, c’est quand même l’un des outils les plus utiles à apprendre tôt.
Un match simple
Section intitulée « Un match simple »fn main() { let day = 3;
match day { 1 => println!("Lundi"), 2 => println!("Mardi"), 3 => println!("Mercredi"), 4 => println!("Jeudi"), 5 => println!("Vendredi"), _ => println!("Week-end"), }}Sortie :
MercrediLe _ est un motif « attrape-tout » : il correspond à tout ce qui n’est pas listé au-dessus. match exige que chaque valeur possible soit traitée, c’est pourquoi _ est souvent là pour couvrir « tout le reste ».
Plusieurs valeurs dans une même branche
Section intitulée « Plusieurs valeurs dans une même branche »Vous pouvez regrouper plusieurs valeurs dans une seule branche avec | :
fn main() { let day = 6;
match day { 1 | 2 | 3 | 4 | 5 => println!("Jour de semaine"), 6 | 7 => println!("Week-end"), _ => println!("Jour invalide"), }}Correspondre à une plage
Section intitulée « Correspondre à une plage »Pour les nombres, vous pouvez faire correspondre toute une plage avec ..= :
fn main() { let score = 85;
match score { 90..=100 => println!("A"), 75..=89 => println!("B"), 60..=74 => println!("C"), _ => println!("F"), }}match comme expression
Section intitulée « match comme expression »Comme if, match peut produire une valeur :
fn main() { let day = 6;
let kind = match day { 1 | 2 | 3 | 4 | 5 => "jour de semaine", 6 | 7 => "week-end", _ => "inconnu", };
println!("{kind}");}Correspondre à du texte et à des caractères
Section intitulée « Correspondre à du texte et à des caractères »match ne sert pas qu’aux nombres. Il fonctionne aussi avec les string slices (&str) et les caractères, et les plages de caractères comme 'a'..='z' marchent exactement comme les plages de nombres :
fn main() { let command = "stop"; match command { "start" => println!("Démarrage..."), "stop" | "quit" => println!("Arrêt."), _ => println!("Commande inconnue : {command}"), }
let letter = 'k'; let kind = match letter { 'a' | 'e' | 'i' | 'o' | 'u' => "voyelle", 'a'..='z' => "consonne", '0'..='9' => "chiffre", _ => "autre chose", }; println!("'{letter}' : {kind}");
let name = String::from("Ferris"); match name.as_str() { "Ferris" => println!("Salut, le crabe !"), _ => println!("Salut, {name} !"), }}Sortie :
Arrêt.'k' : consonneSalut, le crabe !Deux choses méritent votre attention :
- L’ordre compte.
'a'fait aussi partie de'a'..='z', mais la branche des voyelles vient en premier : les voyelles n’atteignent donc jamais la branche des consonnes. Rust choisit toujours la première branche qui correspond. - Une
Stringa besoin de.as_str(). Un texte écrit entre guillemets, comme"Ferris", est un&str. Si vous faites unmatchdirectement sur uneString, Rust s’arrête avecerror[E0308]: mismatched types ... expected String, found &str(les types ne correspondent pas : il attendait uneStringet a trouvé un&str). Appeler.as_str()vous donne une vue&strde laString, que les motifs peuvent comparer. (Voir la page Les chaînes de caractères pour la différence entre les deux.)
La correspondance est sensible à la casse : "Stop" ne correspond pas à "stop". Si le texte vient d’un utilisateur, une astuce courante consiste à faire le match sur input.to_lowercase().as_str().
match ou if/else ?
Section intitulée « match ou if/else ? »Les deux conviennent pour un simple test vrai/faux, mais match prend l’avantage dès que vous avez plus de deux ou trois possibilités : il se lit mieux qu’une longue chaîne de else if, et le compilateur vérifie que vous avez couvert tous les cas. if/else reste le bon outil pour une seule condition oui/non.
Exercices
Section intitulée « Exercices »1. Nombre de jours dans un mois
Section intitulée « 1. Nombre de jours dans un mois »Stockez un numéro de mois month (2). Utilisez match comme expression pour calculer combien de jours il compte (sans tenir compte des années bissextiles), puis affichez Le mois 2 a 28 jours. Indice : les mois 1, 3, 5, 7, 8, 10 et 12 ont 31 jours ; regroupez-les dans une seule branche avec |.
Voir la solution
fn main() { let month = 2;
let days = match month { 1 | 3 | 5 | 7 | 8 | 10 | 12 => 31, 4 | 6 | 9 | 11 => 30, 2 => 28, _ => 0, // ce n'est pas un vrai mois };
println!("Le mois {month} a {days} jours");}Sortie :
Le mois 2 a 28 jours2. Codes de statut HTTP
Section intitulée « 2. Codes de statut HTTP »Les serveurs web répondent avec un nombre. Transformez un code en une courte explication : 200 donne "OK", 404 donne "Not Found", tout autre code entre 400 et 499 donne "Erreur client", entre 500 et 599 "Erreur serveur", et tout le reste "Inconnu". Essayez avec 503. Indice : placez la branche exacte 404 au-dessus de la plage 400..=499, sinon elle ne sera jamais atteinte.
Voir la solution
fn main() { let code = 503;
let meaning = match code { 200 => "OK", 404 => "Not Found", // doit venir avant la plage 400..=499 400..=499 => "Erreur client", 500..=599 => "Erreur serveur", _ => "Inconnu", };
println!("{code} : {meaning}");}Sortie :
503 : Erreur serveur"OK" et "Not Found" restent en anglais : ce sont les libellés officiels que renvoient les serveurs HTTP.
Récapitulatif
Section intitulée « Récapitulatif »matchcompare une valeur à des motifs et exécute la branche qui correspond.- Chaque valeur possible doit être traitée : utilisez
_comme attrape-tout. - Regroupez des valeurs avec
|, ou faites correspondre une plage avec..=. - Vous pouvez aussi faire un
matchsur du texte&stret des valeurschar; utilisez.as_str()pour uneString. - Comme
if,matchpeut servir d’expression pour produire une valeur.
Petit quiz
Section intitulée « Petit quiz »Petit quiz
1. À quoi sert le motif _ dans une expression match ?
2. Que se passe-t-il si un match ne traite pas toutes les valeurs possibles et n'a pas de branche _ ?
3. Comment faire correspondre plusieurs valeurs dans une même branche, comme 1, 2 ou 3 ?
Score : 0 / 3
Pour aller plus loin
Section intitulée « Pour aller plus loin »- The match Control Flow Construct — The Rust Book (en anglais) : le chapitre officiel, qui montre aussi
matchsur des enums et surOption. - match — Rust by Example (en anglais) : un exemple court et exécutable avec des valeurs,
|, des plages et_. - Range patterns — The Rust Reference (en anglais) : exactement quels types et quelles formes de plages sont utilisables dans un motif.
- Match expressions — The Rust Reference (en anglais) : les règles précises des branches, des gardes et de la façon dont un
matchproduit sa valeur.