Flusso di controllo conciso con if let
La sintassi if let
ti consente di combinare if
e let
in un modo meno verbose per gestire valori che corrispondono a un modello mentre ignora il resto. Considera il programma nel Listing 6-6 che corrisponde su un valore Option<u8>
nella variabile config_max
ma vuole eseguire codice solo se il valore è la variante Some
.
fn main() { let config_max = Some(3u8); match config_max { Some(max) => println!("The maximum is configured to be {}", max), _ => (), } }
Se il valore è Some
, stampiamo il valore nella variante Some
legando il valore alla variabile max
nel modello. Non vogliamo fare nulla con il valore None
. Per soddisfare l'espressione match
, dobbiamo aggiungere _ => ()
dopo aver processato solo una variante, il che è fastidioso boilerplate code da aggiungere.
Invece, potremmo scrivere questo in un modo più breve usando if let
. Il seguente codice si comporta allo stesso modo del match
nel Listing 6-6:
fn main() { let config_max = Some(3u8); if let Some(max) = config_max { println!("The maximum is configured to be {}", max); } }
La sintassi if let
prende un modello e un'espressione separati da un segno uguale. Funziona allo stesso modo di un match
, dove l'espressione viene data al match
e il modello è il suo primo ramo. In questo caso, il modello è Some(max)
, e max
si lega al valore all'interno di Some
. Possiamo quindi usare max
nel blocco if let
allo stesso modo in cui usavamo max
nel corrispondente ramo del match
. Il codice nel blocco if let
non viene eseguito se il valore non corrisponde al modello.
Usare if let
significa meno digitazione, meno indentazione e meno boilerplate code. Tuttavia, si perde il controllo esaustivo che match
impone. Scegliere tra match
e if let
dipende da quello che stai facendo nella tua particolare situazione e se ottenere concisione è un compromesso appropriato per perdere il controllo esaustivo.
In altre parole, puoi pensare a if let
come a zucchero sintattico per un match
che esegue 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 il else
è lo stesso del blocco di codice che andrebbe con il caso _
nell'espressione match
che è equivalente al if let
e else
. Ricorda la definizione dell'Enum
Coin
nel Listing 6-4, dove la variante Quarter
deteneva anche un valore UsState
. Se volessimo contare tutte le monete non-quarter che vediamo annunciando anche lo stato dei quarters, potremmo farlo con un'espressione match
, come questa:
#[derive(Debug)] enum UsState { Alabama, Alaska, // --snip-- } enum Coin { Penny, Nickel, Dime, Quarter(UsState), } fn main() { let coin = Coin::Penny; let mut count = 0; match coin { Coin::Quarter(state) => println!("State quarter from {:?}!", state), _ => count += 1, } }
Oppure potremmo usare un'espressione if let
e else
, come questa:
#[derive(Debug)] enum UsState { Alabama, Alaska, // --snip-- } enum Coin { Penny, Nickel, Dime, Quarter(UsState), } fn main() { let coin = Coin::Penny; let mut count = 0; if let Coin::Quarter(state) = coin { println!("State quarter from {:?}!", state); } else { count += 1; } }
Se hai una situazione in cui il tuo programma ha una logica che è troppo prolissa da esprimere usando un match
, ricorda che if let
è anche nella tua cassetta degli attrezzi di Rust.
Sommario
Abbiamo ora coperto come utilizzare gli enum per creare tipi personalizzati che possono essere uno di un set di valori enumerati. Abbiamo mostrato come il tipo Option<T>
della libreria standard aiuta a utilizzare il sistema di tipi per prevenire errori. Quando i valori enum contengono dati al loro interno, puoi utilizzare match
o if let
per estrarre e usare quei valori, a seconda di quanti casi devi gestire.
I tuoi programmi Rust possono ora esprimere concetti nel tuo dominio usando struct ed enum. Creare tipi personalizzati da usare nella tua API garantisce la sicurezza dei tipi: il compilatore si assicurerà che le tue funzioni ricevano solo valori del tipo che ciascuna funzione si aspetta.
Per fornire un'API ben organizzata ai tuoi utenti che sia semplice da usare e esponga solo ciò di cui gli utenti hanno bisogno, rivolgiamoci ora ai moduli di Rust.