La boucle for en Rust
for parcourt un intervalle ou une collection, un élément à la fois. Des trois types de boucles de Rust, c’est celle que vous utiliserez le plus souvent.
Parcourir un intervalle
Section intitulée « Parcourir un intervalle »fn main() { for i in 1..=5 { println!("{i}"); }}Sortie :
123451..=5 est un intervalle (range) qui inclut ses deux bornes (de 1 à 5). Si vous retirez le =, 1..5 s’arrête un cran plus tôt et vous donne 1 à 4. Ce décalage d’une unité est facile à rater : vérifiez bien lequel des deux vous vouliez.
Parcourir une collection
Section intitulée « Parcourir une collection »C’est là que for brille vraiment : parcourir un tableau ou un vecteur sans gérer d’indice vous-même.
fn main() { let fruits = ["pomme", "banane", "cerise"];
for fruit in fruits { println!("{fruit}"); }}Sortie :
pommebananeceriseComparez avec une boucle while qui compte à la main et accède aux éléments par indice (fruits[i]) : c’est plus court, et il n’y a aucun indice à rater. Vous en apprendrez plus sur les tableaux et les vecteurs aux pages Tableaux et Vecteurs.
Récupérer aussi l’indice avec .enumerate()
Section intitulée « Récupérer aussi l’indice avec .enumerate() »Si vous avez besoin à la fois de la position et de la valeur, utilisez .enumerate() :
fn main() { let fruits = ["pomme", "banane", "cerise"];
for (index, fruit) in fruits.iter().enumerate() { println!("{index}: {fruit}"); }}Sortie :
0: pomme1: banane2: ceriseLa partie (index, fruit) est un pattern de tuple : à chaque tour, vous recevez une paire, et la boucle la découpe pour vous en deux variables.
Compter à rebours et par pas
Section intitulée « Compter à rebours et par pas »Et si vous voulez compter à rebours depuis 3, ou ne prendre qu’un nombre sur deux ? Le premier réflexe est d’écrire un intervalle à l’envers, comme 3..=1. Ça compile, mais la boucle ne s’exécute jamais. Un intervalle ne compte que vers le haut : si son début est plus grand que sa fin, il est tout simplement vide.
À la place, partez d’un intervalle normal et changez la façon de le parcourir :
.rev()parcourt l’intervalle à l’envers..step_by(n)prend une valeur toutes lesn, en commençant par la première.
fn main() { for i in (1..=3).rev() { println!("{i}..."); } println!("Partez !");
for even in (0..=10).step_by(2) { print!("{even} "); } println!();
for i in 3..=1 { println!("ceci ne s'affiche jamais : {i}"); }}Sortie :
3...2...1...Partez !0 2 4 6 8 10Remarquez les parenthèses : (1..=3).rev(). Sans elles, Rust lirait 1..=3.rev() comme « de 1 jusqu’à 3.rev() », ce qui n’est pas ce que vous voulez. Vous pouvez aussi combiner les deux : (0..=10).rev().step_by(5) donne 10, 5, 0.
Pourquoi préférer for à while pour compter
Section intitulée « Pourquoi préférer for à while pour compter »Vous pourriez écrire une boucle qui compte avec while, mais for avec un intervalle élimine toute une catégorie d’erreurs : pas de compteur à mettre à jour (et donc à oublier), et aucun risque de dépasser d’un cran la fin d’un tableau. Les développeurs Rust utilisent for par défaut et ne passent à while que lorsqu’il n’y a pas d’intervalle ou de collection naturelle à parcourir.
Exercices
Section intitulée « Exercices »1. Une table de multiplication
Section intitulée « 1. Une table de multiplication »Affichez la table de 7, de 7 x 1 = 7 jusqu’à 7 x 10 = 70. Indice : une seule boucle for sur 1..=10 suffit. Vous pouvez faire la multiplication directement dans println!.
Voir la solution
fn main() { for i in 1..=10 { println!("7 x {i} = {}", 7 * i); }}Sortie :
7 x 1 = 77 x 2 = 147 x 3 = 217 x 4 = 287 x 5 = 357 x 6 = 427 x 7 = 497 x 8 = 567 x 9 = 637 x 10 = 70Les noms de variables comme {i} peuvent aller directement entre les accolades. Un calcul comme 7 * i, non : on utilise donc des accolades vides {} et on met la valeur après la virgule.
2. Additionner les nombres impairs
Section intitulée « 2. Additionner les nombres impairs »Additionnez tous les nombres impairs de 1 à 99 et affichez le total. Indice : (1..100).step_by(2) vous donne 1, 3, 5, … 99. Gardez un total mut en dehors de la boucle.
Voir la solution
fn main() { let mut total = 0;
for n in (1..100).step_by(2) { total += n; }
println!("La somme des nombres impairs de 1 à 99 vaut {total}");}Sortie :
La somme des nombres impairs de 1 à 99 vaut 2500Une autre solution consiste à parcourir 1..100 et à n’ajouter n que si n % 2 == 1. Les deux fonctionnent. step_by saute simplement les nombres pairs au lieu de tester chacun d’eux.
Récapitulatif
Section intitulée « Récapitulatif »for element in intervalle_ou_collection { ... }est la boucle de tous les jours en Rust.1..=5inclut les deux bornes ;1..5s’arrête juste avant 5.- Parcourez directement les tableaux et les vecteurs pour obtenir chaque valeur sans gérer d’indice.
- Utilisez
.enumerate()quand vous avez besoin de l’indice en plus de la valeur. - Un intervalle à l’envers comme
3..=1est vide. Utilisez(1..=3).rev()pour compter à rebours, et.step_by(n)pour avancer par pas.
Petit quiz
Section intitulée « Petit quiz »Petit quiz
1. Quelle est la différence entre 1..=5 et 1..5 dans une boucle for ?
2. Comment obtenir à la fois l'indice et la valeur en parcourant une collection ?
3. Pourquoi préfère-t-on généralement for à while pour parcourir une collection ?
4. Que fait for i in 5..=1 { ... } ?
Score : 0 / 4
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Looping Through a Collection with for — The Rust Book (en anglais) : la présentation officielle, avec un compte à rebours utilisant
.rev(). - for and range — Rust by Example (en anglais) : des exemples exécutables d’intervalles, ainsi que
iter,iter_mutetinto_iterpour les collections. - Iterator loops — The Rust Reference (en anglais) : les règles exactes de ce que fait une boucle
foren coulisses. Iterator::step_by— documentation de la bibliothèque standard (en anglais) : le fonctionnement destep_by, avec des exemples.revest documentée sur la même page.