I. Les bases de la programmation en Rust
11. if let / while let
Maintenant que nous avons vu ce qu'étaient les enums, je peux vous parler de if let
et de while let
.
Qu'est-ce que le if let ?
Le if let
permet de simplifier certains traitements de pattern matching. Prenons un exemple :
Runfn fais_quelque_chose(i: i32) -> Option<String> {
if i < 10 {
Some("variable inférieure à 10".to_owned())
} else {
None
}
}
Normalement, pour vérifier le retour de cette fonction, vous utiliseriez un match
:
Runmatch fais_quelque_chose(1) {
Some(s) => println!("{}", &s),
None => {} // rien à afficher donc on ne fait rien
}
Et bien avec le if let
vous pouvez faire :
Runif let Some(s) = fais_quelque_chose(1) {
println!("{}", &s)
}
Et c'est tout. Pour faire simple, si le type renvoyé par la fonction fais_quelque_chose
correspond à celui donné au if let
, le code du if
sera exécuté. On peut bien évidemment le coupler avec un else if
ou avec un else
:
Runif let Some(s) = fais_quelque_chose(1) {
println!("{}", &s)
} else {
println!("il ne s'est rien passé")
}
Essayez en passant un nombre supérieur à 10 comme argument, vous devriez rentrer dans le else
.
D'ailleurs, je ne l'ai pas précisé dans le chapitre "Conditions et pattern matching" mais il est possible d'être plus précis dans le pattern matching en utilisant plusieurs niveaux de types. Par exemple :
Runlet x = Some(10);
// on rentre dans ce if si x est un Option::Some contenant 10 !
if let Some(10) = x {
// ...
} else if let Some(11) = x {
// ...
}
Vous pouvez bien évidemment le faire sur autant de "niveaux" que vous le souhaitez :
Runlet x = Ok(Some(Ok(Ok(2))));
if let Ok(Some(Ok(Ok(2)))) = x {
// ...
}
while let
Le while let
fonctionne de la même façon : tant que le type renvoyé correspondra au type attendu, la boucle continuera. Donc le code suivant :
Runlet mut v = vec!(1, 2, 3);
loop {
match v.pop() {
Some(x) => println!("{}", x),
None => break,
}
}
Deviendra :
Runlet mut v = vec!(1, 2, 3);
while let Some(x) = v.pop() {
println!("{}", x);
}
Déstructuration
Dans le précédent chapitre, je vous ai rapidement montré ce qu'était la déstructuration. Cela fonctionne bien évidemment pour while let
et if let
:
Runstruct Point {
x: i32,
y: i32,
}
let origin = Point { x: 0, y: 0 };
match origin {
Point { x, y } => println!("({},{})", x, y),
}
// est équivalent à :
if let Point { x, y } = origin {
println!("({},{})", x, y);
}