Pattern matching
1. L'expression match
match compare une valeur contre une liste de motifs et exécute la branche correspondante.
let nombre = 7;
match nombre {
1 => println!("un"),
2 | 3 => println!("deux ou trois"),
4..=6 => println!("entre 4 et 6"),
n => println!("autre : {n}"), // variable de capture
}
Important :
matchest exhaustif — toutes les variantes doivent être couvertes. Le compilateur l'impose.
// Utiliser _ pour ignorer les cas restants
match nombre {
1 => println!("un"),
_ => println!("autre"),
}
2. Motifs courants
2.1 Littéraux et plages
let c = 'a';
match c {
'a'..='z' => println!("minuscule"),
'A'..='Z' => println!("majuscule"),
'0'..='9' => println!("chiffre"),
_ => println!("autre caractère"),
}
2.2 Destructurer les enums
enum Message {
Quitter,
Deplacer { x: i32, y: i32 },
Ecrire(String),
ChangerCouleur(u8, u8, u8),
}
let msg = Message::Deplacer { x: 10, y: 20 };
match msg {
Message::Quitter => println!("quitter"),
Message::Deplacer { x, y } => println!("déplacer vers {x},{y}"),
Message::Ecrire(texte) => println!("écrire : {texte}"),
Message::ChangerCouleur(r, g, b) => println!("couleur : {r},{g},{b}"),
}
2.3 Destructurer les structs
struct Point { x: i32, y: i32 }
let p = Point { x: 3, y: 7 };
// Destructuration complète
let Point { x, y } = p;
println!("{x}, {y}");
// Dans un match
match p {
Point { x: 0, y } => println!("sur l'axe Y à {y}"),
Point { x, y: 0 } => println!("sur l'axe X à {x}"),
Point { x, y } => println!("({x}, {y})"),
}
2.4 Destructurer les tuples
let tuple = (1, true, "bonjour");
match tuple {
(1, true, msg) => println!("un, vrai, {msg}"),
(n, false, _) => println!("n={n}, faux"),
_ => println!("autre"),
}
// Destructuration directe
let (a, b, c) = tuple;
2.5 Slices
let nombres = vec![1, 2, 3, 4, 5];
match nombres.as_slice() {
[] => println!("vide"),
[seul] => println!("un seul : {seul}"),
[premier, .., dernier] => println!("de {premier} à {dernier}"),
}
3. Gardes de motif
Une garde (if condition) ajoute un test supplémentaire après le motif.
let pair = (2, -3);
match pair {
(x, y) if x == y => println!("égaux"),
(x, y) if x + y == 0 => println!("opposés"),
(x, _) if x % 2 == 0 => println!("x est pair"),
_ => println!("autre"),
}
Attention : La garde ne participe pas à l'exhaustivité — le compilateur ne peut pas vérifier les conditions arbitraires.
4. if let et while let
if let — pattern unique sans exhaustivité
let valeur: Option<i32> = Some(42);
// Verbeux avec match
match valeur {
Some(n) => println!("got {n}"),
None => {},
}
// Concis avec if let
if let Some(n) = valeur {
println!("got {n}");
}
// Avec else
if let Some(n) = valeur {
println!("got {n}");
} else {
println!("rien");
}
while let — boucle tant que le motif correspond
let mut pile = vec![1, 2, 3];
while let Some(sommet) = pile.pop() {
println!("{sommet}");
}
// Affiche : 3, 2, 1
5. Patterns avancés
`@` — capturer et tester
let n = 15;
match n {
x @ 1..=12 => println!("mois {x}"),
x @ 13..=19 => println!("ado {x}"),
_ => println!("autre"),
}
`..` — ignorer les champs restants
struct Point3D { x: i32, y: i32, z: i32 }
let p = Point3D { x: 1, y: 2, z: 3 };
match p {
Point3D { x, .. } => println!("x = {x}"), // y et z ignorés
}
// Dans un tuple
let tuple = (1, 2, 3, 4, 5);
let (premier, .., dernier) = tuple;
`|` — plusieurs motifs
match valeur {
1 | 2 | 3 => println!("petit"),
4 | 5 | 6 => println!("moyen"),
_ => println!("grand"),
}
`ref` et `ref mut` — emprunter dans un motif
let texte = String::from("bonjour");
match texte {
ref s => println!("longueur : {}", s.len()), // s est &String
}
// texte est toujours valide ici
println!("{texte}");
let-else (Rust 1.65+)
fn parse_id(s: &str) -> u32 {
let Ok(id) = s.parse::<u32>() else {
panic!("id invalide : {s}");
};
id
}