Match in Rust
match confronta un valore con una lista di pattern ed esegue il codice di quello che corrisponde. Pensalo come una versione più potente dell’istruzione switch, se ne hai mai usata una; e se non l’hai mai fatto, resta comunque uno degli strumenti più utili da imparare presto.
Match di base
Sezione intitolata “Match di base”fn main() { let day = 3;
match day { 1 => println!("Lunedì"), 2 => println!("Martedì"), 3 => println!("Mercoledì"), 4 => println!("Giovedì"), 5 => println!("Venerdì"), _ => println!("Fine settimana"), }}Output:
MercoledìIl _ è un jolly (catch-all): corrisponde a qualsiasi cosa non elencata sopra. match richiede che ogni valore possibile sia gestito, quindi di solito c’è _ a coprire «tutto il resto».
Più valori in un colpo solo
Sezione intitolata “Più valori in un colpo solo”Puoi raggruppare più valori in un unico ramo usando |:
fn main() { let day = 6;
match day { 1 | 2 | 3 | 4 | 5 => println!("Giorno feriale"), 6 | 7 => println!("Fine settimana"), _ => println!("Giorno non valido"), }}Un intervallo di valori
Sezione intitolata “Un intervallo di valori”Per i numeri puoi far corrispondere un intero intervallo con ..=:
fn main() { let score = 85;
match score { 90..=100 => println!("A"), 75..=89 => println!("B"), 60..=74 => println!("C"), _ => println!("F"), }}match come espressione
Sezione intitolata “match come espressione”Proprio come if, anche match può produrre un valore:
fn main() { let day = 6;
let kind = match day { 1 | 2 | 3 | 4 | 5 => "feriale", 6 | 7 => "fine settimana", _ => "sconosciuto", };
println!("{kind}");}Testo e caratteri
Sezione intitolata “Testo e caratteri”match non serve solo per i numeri. Funziona anche con le slice di stringa (&str) e con i caratteri, e gli intervalli di caratteri come 'a'..='z' funzionano proprio come quelli numerici:
fn main() { let command = "ferma"; match command { "avvia" => println!("Avvio..."), "ferma" | "esci" => println!("Mi fermo."), _ => println!("Comando sconosciuto: {command}"), }
let letter = 'k'; let kind = match letter { 'a' | 'e' | 'i' | 'o' | 'u' => "vocale", 'a'..='z' => "consonante", '0'..='9' => "cifra", _ => "qualcos'altro", }; println!("'{letter}' è una {kind}");
let name = String::from("Ferris"); match name.as_str() { "Ferris" => println!("Ciao, granchio!"), _ => println!("Ciao, {name}!"), }}Output:
Mi fermo.'k' è una consonanteCiao, granchio!Due cose da notare:
- L’ordine conta. Anche
'a'sta dentro'a'..='z', ma il ramo delle vocali viene prima, quindi le vocali non arrivano mai al ramo delle consonanti. Rust sceglie sempre il primo ramo che corrisponde. - Una
Stringha bisogno di.as_str(). Il testo scritto tra virgolette, come"Ferris", è un&str. Se fai ilmatchdi unaStringdirettamente contro di esso, Rust si ferma conerror[E0308]: mismatched types ... expected String, found &str(tipi non corrispondenti: si aspettava unaStringe ha trovato un&str). Chiamare.as_str()ti dà una vista&strdellaStringcon cui i pattern possono confrontarsi. (Vedi la pagina Stringhe per la differenza tra i due.)
Il confronto distingue maiuscole e minuscole: "Ferma" non corrisponderebbe a "ferma". Se il testo arriva da un utente, un trucco comune è fare il match su input.to_lowercase().as_str().
match contro if/else
Sezione intitolata “match contro if/else”Per i semplici controlli vero/falso vanno bene entrambi, ma match comincia a vincere quando hai più di due o tre possibilità: si legge meglio di una lunga catena di else if, e il compilatore controlla che tu abbia coperto ogni caso. if/else resta lo strumento giusto per una singola condizione sì/no.
Pratica
Sezione intitolata “Pratica”1. Giorni del mese
Sezione intitolata “1. Giorni del mese”Salva il numero di un mese, month (2). Usa match come espressione per calcolare quanti giorni ha (ignora gli anni bisestili), poi stampa Il mese 2 ha 28 giorni. Suggerimento: i mesi 1, 3, 5, 7, 8, 10 e 12 hanno 31 giorni; raggruppali in un unico ramo con |.
Mostra la soluzione
fn main() { let month = 2;
let days = match month { 1 | 3 | 5 | 7 | 8 | 10 | 12 => 31, 4 | 6 | 9 | 11 => 30, 2 => 28, _ => 0, // non è un mese vero };
println!("Il mese {month} ha {days} giorni");}Output:
Il mese 2 ha 28 giorni2. Codici di stato HTTP
Sezione intitolata “2. Codici di stato HTTP”I server web rispondono con un numero. Trasforma un code in un breve significato: 200 è "OK", 404 è "Non trovato", qualsiasi altro tra 400 e 499 è "Errore del client", tra 500 e 599 è "Errore del server", e tutto il resto è "Sconosciuto". Provalo con 503. Suggerimento: metti il ramo esatto 404 sopra l’intervallo 400..=499, altrimenti non verrà mai raggiunto.
Mostra la soluzione
fn main() { let code = 503;
let meaning = match code { 200 => "OK", 404 => "Non trovato", // deve venire prima dell'intervallo 400..=499 400..=499 => "Errore del client", 500..=599 => "Errore del server", _ => "Sconosciuto", };
println!("{code}: {meaning}");}Output:
503: Errore del serverRiepilogo
Sezione intitolata “Riepilogo”matchconfronta un valore con dei pattern ed esegue il ramo che corrisponde.- Ogni valore possibile deve essere gestito: usa
_come jolly. - Combina più valori con
|, o fai corrispondere un intervallo con..=. - Puoi fare il
matchanche di testo&stre di valorichar; usa.as_str()per unaString. match, comeif, si può usare come espressione per produrre un valore.
Verifica veloce
Sezione intitolata “Verifica veloce”Verifica veloce
1. Cosa fa il pattern _ in un'espressione match?
2. Cosa succede se un'espressione match non gestisce ogni valore possibile e non ha un ramo _?
3. Come fai corrispondere più valori in un unico ramo, come 1, 2 o 3?
Punteggio: 0 / 3
Per approfondire
Sezione intitolata “Per approfondire”- The match Control Flow Construct — The Rust Book (in inglese): il capitolo ufficiale, che mostra anche
matchsu enum eOption. - match — Rust by Example (in inglese): un esempio eseguibile compatto con valori,
|, intervalli e_. - Range patterns — The Rust Reference (in inglese): esattamente quali tipi e forme di intervallo puoi usare in un pattern.
- Match expressions — The Rust Reference (in inglese): le regole precise per i rami, le guardie e come un
matchproduce il suo valore.