Astuces Rust pour match : gérer les vecteurs selon leur longueur
- 6 juin 2025
- 6 mins de lecture
- Programmation rust
Table des matières
​
La situation que vous avez déjà rencontrée
Vous écrivez une fonction Rust qui reçoit un Vec<T>. Et selon le nombre d’éléments (1, 2, 3 ou 4), vous devez exécuter un traitement différent : appeler d’autres fonctions, transmettre les valeurs à des handlers, etc.
En dehors de cette plage, c’est une erreur. Et quand on débute, on finit généralement avec ce genre de code :
1fn process(vec: Vec<i32>) -> Result<(), String> {
2 if vec.len() < 1 || vec.len() > 4 {
3 return Err("Invalid number of elements".to_string());
4 }
5
6 if vec.len() == 1 {
7 func1(vec[0]);
8 } else if vec.len() == 2 {
9 func2(vec[0], vec[1]);
10 } else if vec.len() == 3 {
11 func3(vec[0], vec[1], vec[2]);
12 } else {
13 func4(vec[0], vec[1], vec[2], vec[3]);
14 }
15 Ok(())
16}
Ce code fonctionne, mais il n’est ni élégant, ni idiomatique.
Chaque accès vec[i] suppose que l’indice est valide, et la logique devient vite bruyante.
Alors… comment faire mieux en Rust ?
​
Place à match — idiomatique, expressif et 100% sûr
Rust propose un outil puissant qui dépasse le simple “switch-case” : le pattern matching avec match.
Voici exactement la même logique, mais plus claire, plus sûre et beaucoup plus Rust :
1fn process(vec: Vec<i32>) -> Result<(), String> {
2 match vec.as_slice() {
3 [a] => func1(*a),
4 [a, b] => func2(*a, *b),
5 [a, b, c] => func3(*a, *b, *c),
6 [a, b, c, d] => func4(*a, *b, *c, *d),
7 _ => return Err("Invalid number of elements".to_string()),
8 }
9 Ok(())
10}
Ce modèle est une démonstration parfaite du match sur slice et pattern matching sur vecteur en Rust.
D’un coup, l’intention est limpide. Et le compilateur vous protège contre toute erreur d’indexation.
Note
as_slice() renvoie &[T], donc chaque valeur est une référence.
Vous pouvez aussi matcher directement les références :
1match vec.as_slice() {
2 [&a] => func1(a),
3 [&a, &b] => func2(a, b),
4 _ => ...
5}
​
Pourquoi cette approche est nettement supérieure
Voici les avantages principaux — tous valables dans des projets Rust réels :
-
✔ Lisibilité immédiate: Chaque cas exprime exactement ce qu’il attend :
[a],[a, b],[a, b, c]… -
✔ Sécurité renforcée: Plus de risques de sortir des bornes avec
vec[i]. -
✔ Extensible sans douleur: Vous devez gérer un vecteur de 5 éléments ? Ajoutez un bras de
match: c’est tout. -
✔ Idiomatique Rust: Ce style « sonne Rust » pour un Rustacean 1.
-
✔ Aide du compilateur: Si vous oubliez un cas, Rust vous prévient. Aucun risque de logique incomplète.
-
✔ Des noms explicites: Vous pouvez nommer correctement chaque valeur, et pas seulement
vec[0]. Cette clarté supplémentaire joue beaucoup, surtout dans une logique plus complexe. Par example :
1match vec.as_slice() {
2 [x] => handle_single(x),
3 [x, y] => handle_pair(x, y),
4 [start, middle, end] => handle_triplet(start, middle, end),
5 _ => return Err("Invalid input".to_string()),
6}
Warning
Évitez vec[0] ou .get(0).unwrap() tant que la longueur n’est pas garantie.
Avec le pattern matching, impossible d’oublier un cas critique.
​
Cas d’usage réels : tirer pleinement parti du pattern matching Rust
Le pattern matching sur slices et vecteurs n’est pas seulement élégant — c’est extrêmement puissant en pratique.
Voici des patterns utiles pour enrichir votre code Rust.
​
1. Ajouter des conditions avec des (if) guards
1match vec.as_slice() {
2 [a, b] if a == b => handle_equal_pair(a),
3 [a, b] => handle_unequal_pair(a, b),
4 _ => return Err("Unsupported input".to_string()),
5}
Vous gagnez une expressivité incroyable sans empiler les conditions.
​
2. Matching imbriqué sur les valeurs internes
Exemple typique avec des Option :
1match vec.as_slice() {
2 [Some(a), Some(b)] => handle_both_present(a, b),
3 [Some(a), None] => handle_partial(a),
4 _ => return Err("Invalid combination".to_string()),
5}
Très utile lorsqu’on manipule des enums imbriquées.
​
3. Match partiel avec “splat” (..)
1match vec.as_slice() {
2 [first, .., last] => handle_ends(first, last),
3 _ => return Err("Too short".to_string()),
4}
Parfait pour les algorithmes où seul le début et la fin comptent.
​
4. Modifier les valeurs sur place grâce à as_mut_slice()
1fn double_first(vec: &mut Vec<i32>) -> Result<(), String> {
2 match vec.as_mut_slice() {
3 [x, ..] => {
4 *x *= 2;
5 Ok(())
6 },
7 [] => Err("Empty vector".to_string()),
8 }
9}
Et pour plusieurs éléments :
1match vec.as_mut_slice() {
2 [a, b] => {
3 *a += 1;
4 *b *= 2;
5 },
6 _ => return Err("Expected exactly two items".to_string()),
7}
Idéal pour manipuler des données sans risque (évite les vec[0] += 1 susceptibles de paniquer).
​
5. Cas avancé : matcher des Rc
1use std::rc::Rc;
2
3match vec.as_slice() {
4 [a, b] if Rc::strong_count(a) > 1 => handle_shared(a, b),
5 [a, b] => handle_unique(a, b),
6 _ => return Err("Unexpected input".to_string()),
7}
Même avec des smart pointers, le pattern matching reste puissant.
Attention : déplacer la valeur hors d’un Rc est complexe — il faut souvent cloner ou restructurer.
​
Pourquoi éviter match vec.len() — même si ça semble logique
Beaucoup de développeurs venant de C/C++/Go/Java écrivent ceci instinctivement :
1match vec.len() {
2 1 => process1(vec[0]),
3 2 => process2(vec[0], vec[1]),
4 3 => process3(vec[0], vec[1], vec[1]), // ❌ erreur silencieuse
5 _ => return Err("Invalid input length".to_string()),
6}
Le problème ? Le compilateur ne peut rien vérifier pour vous.
- Vous pouvez vous tromper d’indice (comme ci-dessus).
- Impossible de nommer vos valeurs.
- Aucune vérification de structure.
- Aucune cohérence entre le match et l’accès.
Cette approche compile… mais elle est dangereuse.
Avec les slices, le compilateur vous protège.
Bulletin d'information
Abonnez-vous à notre bulletin d'information et restez informé(e).
​
Conclusion : utilisez match pour décrire la structure d’un vecteur
Quand votre logique dépend du nombre et de la structure des éléments, match avec des slices est l’outil Rust le plus propre, le plus sûr et le plus lisible.
Il évite les pièges liés à l’indexation, s’intègre naturellement avec les enums, les smart pointers, les mutations, et rend votre intention absolument claire.
Rust n’est pas qu’un langage sûr : c’est un langage qui pousse à écrire du code élégant et correct.
​
TL;DR
match + sliceest la meilleure façon de gérer les vecteurs de longueur spécifique.- Code lisible, sûr, extensible et idiomatique.
- Guard, patterns partiels, matching imbriqué → hyper puissant.
- N’utilisez pas
match vec.len()sauf cas très trivial. - Rust n’est pas seulement fait pour éviter les bugs — il est conçu pour favoriser la clarté.
- Idéal pour tout ce qui concerne match sur longueur de vecteur, pattern matching sur slice, etc.
Vous débutez en Rust ? Découvrez cette sélection de ressources et conventions ici.
-
Rustacean désigne quelqu’un maîtrisant Rust, comme « Pythonista » pour Python. ↩︎