
Conditions `if/else` et expressions
Apprenez à utiliser les structures conditionnelles `if/else` et `else if` en Rust, et découvrez comment elles peuvent agir comme des expressions pour assigner des valeurs.
Prendre des décisions en Rust : la puissance des conditions `if/else`
La capacité à prendre des décisions et à exécuter différents chemins de code en fonction de certaines conditions est fondamentale en programmation. En Rust, la structure de contrôle `if/else` est l'outil principal pour implémenter cette logique conditionnelle. Elle permet à votre programme de réagir dynamiquement à différentes situations, rendant le code plus intelligent et adaptable.
Ce sous-chapitre explore en détail la syntaxe et l'utilisation des instructions `if`, `else if`, et `else` en Rust. Nous verrons que la condition d'un `if` doit toujours être une expression booléenne. Plus important encore, nous découvrirons une caractéristique puissante de Rust : le fait que `if/else` est une expression, ce qui signifie qu'elle peut évaluer à une valeur et être utilisée directement dans des assignations.
Comprendre comment manier efficacement les conditions `if/else`, y compris leur utilisation en tant qu'expressions, vous permettra d'écrire du code Rust plus concis, plus lisible et plus expressif pour gérer les multiples branches logiques de vos applications.
Syntaxe de base de `if`, `else if`, et `else`
L'instruction `if` permet d'exécuter un bloc de code si une condition est vraie (`true`). Elle peut être suivie optionnellement par une ou plusieurs clauses `else if` pour tester des conditions supplémentaires si la précédente était fausse, et par une clause `else` finale qui s'exécute si toutes les conditions précédentes étaient fausses.
La condition fournie à une instruction `if` ou `else if` doit impérativement s'évaluer à un type booléen (`bool`). Rust ne convertira pas automatiquement des types non booléens en booléens (par exemple, un entier non nul n'est pas traité comme `true`).
Voici la syntaxe et des exemples d'utilisation :
fn main() {
let nombre = 15;
// Simple if
if nombre > 10 {
println!("Le nombre {} est plus grand que 10.", nombre);
}
// if avec else
let autre_nombre = 3;
if autre_nombre % 2 == 0 {
println!("Le nombre {} est pair.", autre_nombre);
} else {
println!("Le nombre {} est impair.", autre_nombre);
}
// if avec else if et else
let score = 85;
if score >= 90 {
println!("Grade A");
} else if score >= 80 {
println!("Grade B"); // Ce bloc sera exécuté
} else if score >= 70 {
println!("Grade C");
} else {
println!("Grade D ou F");
}
// Condition doit être un booléen
// let condition_non_booleenne = 1;
// if condition_non_booleenne { // ERREUR: expected `bool`, found `i32`
// println!("Cela ne compile pas !");
// }
}Les blocs de code associés à chaque clause `if`, `else if`, ou `else` sont délimités par des accolades `{}`. Si un bloc ne contient qu'une seule instruction, les accolades sont toujours requises, contrairement à certains autres langages. Cela améliore la clarté et évite des erreurs courantes.
`if/else` en tant qu'expression : assigner des valeurs conditionnellement
Une caractéristique particulièrement élégante et puissante de Rust est que `if/else` est une expression. Cela signifie qu'une structure `if/else` peut s'évaluer à une valeur, qui peut ensuite être assignée à une variable à l'aide d'une instruction `let`.
Pour qu'un `if/else` puisse être utilisé comme une expression, il y a une condition importante : toutes les branches (c'est-à-dire le bloc `if` et tous les blocs `else if` et `else`) doivent évaluer à des valeurs du même type. Si les types sont différents, le compilateur signalera une erreur. De plus, si vous utilisez un `if` comme expression pour assigner une valeur, une clause `else` est généralement requise pour garantir que la variable reçoive toujours une valeur, quelle que soit la condition (sauf si le type de retour est `()` et que toutes les branches se terminent par des instructions).
Voici comment utiliser `if/else` en tant qu'expression :
fn main() {
let est_actif = true;
let statut_message = if est_actif {
"Utilisateur actif"
} else {
"Utilisateur inactif"
};
// `statut_message` sera "Utilisateur actif"
// Les deux blocs retournent un &str, donc c'est valide.
println!("Statut : {}", statut_message);
let nombre_a_tester = 7;
let description_nombre = if nombre_a_tester > 0 {
String::from("Positif")
} else if nombre_a_tester < 0 {
String::from("Négatif")
} else {
String::from("Zéro")
// Si on essayait de retourner un &str ici, par ex. "Zéro",
// et que les autres branches retournent String, ce serait une erreur de type.
};
// Tous les blocs retournent une String.
println!("Le nombre {} est {}.", nombre_a_tester, description_nombre);
// Exemple avec des types différents (provoquerait une erreur)
// let resultat_mixte = if nombre_a_tester > 5 {
// 100 // i32
// } else {
// "petit" // &str -- ERREUR: `if` and `else` have incompatible types
// };
}L'utilisation de `if/else` en tant qu'expression permet d'écrire du code plus concis et souvent plus lisible, car elle évite d'avoir à déclarer une variable mutable et à l'assigner dans chaque branche. La valeur est directement produite par l'expression `if/else`.
Chaque bloc de code dans un `if/else` utilisé comme expression s'évalue à la valeur de la dernière expression de ce bloc (celle qui n'est pas suivie d'un point-virgule). Si la dernière ligne est une instruction (terminée par un point-virgule), le bloc s'évalue à `()` (le type unité).
Considérations et bonnes pratiques
Lorsque vous utilisez des chaînes de `else if`, l'ordre des conditions est important. La première condition `true` rencontrée verra son bloc exécuté, et les conditions suivantes ne seront pas évaluées. Assurez-vous que l'ordre correspond à la logique souhaitée, en plaçant souvent les conditions plus spécifiques avant les plus générales si elles se chevauchent.
Bien que les `if/else` en tant qu'expressions soient puissants, évitez de créer des structures `if/else` excessivement imbriquées ou complexes. Si vous vous retrouvez avec de nombreuses branches `else if` basées sur la valeur d'une seule variable, le type `enum` et l'expression `match` (que nous aborderons plus tard) pourraient offrir une solution plus claire et plus robuste.
N'oubliez pas la nécessité que toutes les branches d'un `if/else` utilisé comme expression retournent le même type. C'est une source courante d'erreurs pour les débutants, mais le compilateur Rust fournit des messages d'erreur très utiles pour vous aider à identifier et corriger ces problèmes.
En résumé, les structures `if/else` sont des outils essentiels pour contrôler le flux de votre programme. Leur capacité à agir comme des expressions en Rust ajoute une couche d'expressivité qui, utilisée judicieusement, peut grandement améliorer la qualité de votre code. Pensez toujours à la lisibilité et à la simplicité lorsque vous construisez des logiques conditionnelles complexes.