SE VUOI PRENDERE LA CERTIFICAZIONE PER QUESTO CORSO CLICCA QUI
Controllo Flusso Sintattico con if let
La sintassi if let ti permette di combinare if e let in un modo meno verboso per gestire i valori che corrispondono a un certo modello ignorando il resto. Considera il programma nel Listato 6-6 che corrisponde a un valore Option<u8> nella variabile config_max ma vuole eseguire il codice solo se il valore è della variante Some.
rust
let config_max = Some(3u8);
match config_max {
Some(max) => println!("Il massimo è configurato per essere {}", max),
_ => (),
}
Listato 6-6: Un match che si interessa solo all’esecuzione del codice quando il valore è Some
Se il valore è Some, stampiamo il valore della variante Some legando il valore alla variabile max nel modello. Non vogliamo fare nulla con il valore None. Per soddisfare l’espressione di match, dobbiamo aggiungere _ => () dopo aver processato solo una variante, che è un fastidioso codice boilerplate da aggiungere.
Invece, potremmo scriverlo in modo più breve usando if let. Il codice seguente si comporta allo stesso modo del match nel Listato 6-6:
rust
let config_max = Some(3u8);
if let Some(max) = config_max {
println!("Il massimo è configurato per essere {}", max);
}
La sintassi if let prende un modello ed un’espressione separate da un segno di uguale. Funziona allo stesso modo di un match, dove l’espressione viene data al match e il modello è il suo primo braccio. In questo caso, il modello è Some(max), e max si lega al valore dentro il Some. Possiamo quindi usare max nel corpo del blocco if let allo stesso modo in cui abbiamo usato max nel corrispondente braccio di match. Il codice nel blocco if let non viene eseguito se il valore non corrisponde al modello.
Utilizzare if let significa meno digitazione, meno indentazione e meno codice boilerplate. Tuttavia, perdi il controllo esaustivo che match impone. La scelta tra match e if let dipende da cosa stai facendo nella tua situazione specifica e se ottenere concisione è un compromesso appropriato per perdere il controllo esaustivo.
In altre parole, puoi pensare a if let come zucchero sintattico per un match che esegue il codice quando il valore corrisponde a un modello e quindi ignora tutti gli altri valori.
Possiamo includere un else con un if let. Il blocco di codice che va con l’else è lo stesso del blocco di codice che andrebbe con il caso _ nell’espressione di match che è equivalente all’if let e else. Ricorda la definizione di enum Coin nel Listato 6-4, dove la variante Quarter includeva anche un valore UsState. Se volessimo contare tutte le monete non-quarter che vediamo mentre annunciamo anche lo stato dei quarters, potremmo farlo con un’espressione di match, così:
rust
let mut count = 0;
match coin {
Coin::Quarter(state) => println!("Quarter di stato da {:?}!", state),
_ => count += 1,
}
Oppure potremmo usare un’espressione if let ed else, così:
rust
let mut count = 0;
if let Coin::Quarter(state) = coin {
println!("Quarter di stato da {:?}!", state);
} else {
count += 1;
}
Se hai una situazione in cui il tuo programma ha una logica troppo verbosa da esprimere utilizzando un match, ricorda che if let è anche nel tuo toolbox Rust.
Sommario
Abbiamo ora visto come utilizzare gli enum per creare tipi personalizzati che possono essere uno di un insieme di valori enumerati. Abbiamo mostrato come il tipo Option<T> della libreria standard ti aiuta a utilizzare il sistema di tipi per prevenire gli errori. Quando i valori enum hanno dati al loro interno, puoi usare match o if let per estrarre e utilizzare quei valori, a seconda di quanti casi devi gestire.
I tuoi programmi Rust possono ora esprimere concetti nel tuo dominio utilizzando struct ed enum. Creare tipi personalizzati da utilizzare nella tua API garantisce la sicurezza dei tipi: il compilatore si assicurerà che le tue funzioni ottengano solo valori del tipo che ogni funzione si aspetta.
Per fornire una API ben organizzata ai tuoi utenti che sia semplice da usare e che esponga solo ciò di cui i tuoi utenti avranno bisogno, ora passeremo ai moduli di Rust.