Rust offre tipi avanzati che permettono di modellare dati complessi in modo elegante e sicuro. Le struct sono perfette per raggruppare dati correlati, mentre gli enum consentono di rappresentare varianti e stati. Con pattern matching, Rust fornisce un potente strumento per gestire questi tipi in modo chiaro ed espressivo. Infine, tipi speciali come Option e Result aiutano a gestire casi di valore mancante ed errori in modo sicuro.
In questa lezione, esploreremo questi concetti con esempi pratici.
Le struct permettono di raggruppare più valori sotto un unico tipo. Ci sono tre tipi principali di struct in Rust:
Una struct classica ha campi nominati:
struct Persona {
nome: String,
eta: u32,
}
fn main() {
let persona = Persona {
nome: String::from("Alice"),
eta: 30,
};
println!("Nome: {}, Età: {}", persona.nome, persona.eta);
}
Le struct a tuple non hanno nomi di campo, ma utilizzano posizioni:
struct Punto(i32, i32);
fn main() {
let p = Punto(10, 20);
println!("Punto: ({}, {})", p.0, p.1);
}
Le struct unitarie non hanno campi. Vengono spesso utilizzate per implementare trait.
struct Unitaria;
fn main() {
let _u = Unitaria;
}
Gli enum in Rust sono ideali per rappresentare un insieme di varianti. Ogni variante può contenere dati aggiuntivi.
enum Stagione {
Primavera,
Estate,
Autunno,
Inverno,
}
fn main() {
let stagione_corrente = Stagione::Estate;
match stagione_corrente {
Stagione::Primavera => println!("È primavera!"),
Stagione::Estate => println!("È estate!"),
Stagione::Autunno => println!("È autunno!"),
Stagione::Inverno => println!("È inverno!"),
}
}
Ogni variante può contenere dati:
enum Messaggio {
Testo(String),
Coordinata { x: i32, y: i32 },
Numero(i32),
}
fn main() {
let messaggio = Messaggio::Coordinata { x: 10, y: 20 };
match messaggio {
Messaggio::Testo(testo) => println!("Messaggio: {}", testo),
Messaggio::Coordinata { x, y } => println!("Coordinate: ({}, {})", x, y),
Messaggio::Numero(num) => println!("Numero: {}", num),
}
}
matchIl pattern matching in Rust consente di verificare e destrutturare valori complessi in modo conciso e leggibile.
enum Stato {
Online,
Offline,
InRiparazione,
}
fn stato_dispositivo(stato: Stato) {
match stato {
Stato::Online => println!("Il dispositivo è online."),
Stato::Offline => println!("Il dispositivo è offline."),
Stato::InRiparazione => println!("Il dispositivo è in riparazione."),
}
}
fn main() {
let stato = Stato::Online;
stato_dispositivo(stato);
}
_ per Gestire Casi Non Specificatifn valuta(numero: i32) {
match numero {
1 => println!("Uno"),
2 => println!("Due"),
_ => println!("Altro numero"),
}
}
fn main() {
valuta(5);
}
Option e ResultRust non utilizza null, ma fornisce i tipi Option e Result per rappresentare casi di valore mancante ed errori.
Option per Valori MancantiIl tipo Option può essere Some(T) per un valore presente o None per un valore mancante.
fn trova_valore(numero: i32) -> Option {
if numero > 0 {
Some(numero * 2)
} else {
None
}
}
fn main() {
match trova_valore(5) {
Some(valore) => println!("Valore trovato: {}", valore),
None => println!("Nessun valore trovato."),
}
}
Result per Gestire ErroriResult è utilizzato per operazioni che possono fallire. Può essere Ok(T) per un risultato valido o Err(E) per un errore.
fn dividi(a: i32, b: i32) -> Result {
if b == 0 {
Err(String::from("Errore: divisione per zero"))
} else {
Ok(a / b)
}
}
fn main() {
match dividi(10, 0) {
Ok(risultato) => println!("Risultato: {}", risultato),
Err(errore) => println!("{}", errore),
}
}
Rettangolo con campi altezza e larghezza, e implementa una funzione per calcolare l’area.Operazione con varianti per addizione, sottrazione e moltiplicazione, e utilizza match per eseguire l'operazione corrispondente.Option per scrivere una funzione che restituisce il quadrato di un numero positivo o None se il numero è negativo.Result per leggere un file e gestire possibili errori.Le struct e gli enum in Rust ti permettono di modellare i dati in modo preciso ed espressivo, mentre pattern matching e tipi come Option e Result garantiscono un controllo efficace sui flussi di dati e sugli errori. Questi strumenti, insieme, ti aiuteranno a scrivere codice robusto, sicuro e facilmente manutenibile. Nel prossimo articolo esploreremo argomenti come Vettori, Array e Iteratori. Continua a esercitarti con gli esempi forniti e padroneggia questi concetti avanzati di Rust!