Learn Rust Coding · Lezione

Pattern matching avanzato

Padroneggi le espressioni `match` e altre forme di pattern matching per gestire le varianti dei dati in modo conciso ed esaustivo.

Lezione 3 di 311 passaggi

Pattern matching avanzato è una lezione Learn Rust Coding gratuita su CoddyKit. Questa è la lezione 3 di 3. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Learn Rust Coding, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Learn Rust Coding include 3 lezioni in totale.

Alla scoperta del pattern matching

Benvenuto nel mondo del pattern matching in Rust! Questa potente funzionalità consente di controllare il flusso del programma in base alla struttura dei dati.

Invece di limitarsi a verificare l'uguaglianza, è possibile destrutturare i valori, estrarne i componenti ed eseguire codice specifico per diverse forme di dati.

  • È simile a un'istruzione if/else o switch con funzionalità avanzate.
  • Garantisce la completezza: è necessario gestire tutti i pattern possibili.
  • Rende il codice più leggibile e robusto.

Nozioni di base sull'espressione `match`

Il cuore del pattern matching è l'espressione match. Prende un valore e lo confronta con una serie di pattern. Vince il primo pattern che corrisponde!

Ogni "braccio" di un'espressione match è costituito da un pattern e dal codice da eseguire se quel pattern corrisponde.

enum Direction {
  North,
  East,
  South,
  West,
}

fn main() {
  let my_direction = Direction::North;

  match my_direction {
    Direction::North => println!("Going up!"),
    Direction::East => println!("Going right!"),
    Direction::South => println!("Going down!"),
    Direction::West => println!("Going left!"),
  }
}

Corrispondenza con valori letterali e intervalli

È possibile verificare valori letterali specifici (numeri, caratteri, valori booleani) oppure definire intervalli usando ..=. L'operatore | consente di verificare più pattern con un unico braccio.

Ricordi che i pattern vengono verificati in ordine e viene utilizzata la prima corrispondenza.

fn main() {
  let x = 7;

  match x {
    1 => println!("It's one!"),
    2 | 3 => println!("It's two or three!"),
    4..=8 => println!("It's between four and eight!"),
    _ => println!("It's something else!"), // Catch-all
  }

  let character = 'b';
  match character {
    'a'..='e' => println!("Early letter"),
    _ => println!("Other letter"),
  }
}

Destrutturazione delle struct

Il pattern matching dà il meglio di sé quando si destrutturano tipi di dati complessi come le struct. È possibile estrarre singoli campi direttamente in variabili all'interno del braccio di match.

Questo rende l'accesso ai dati di una struct chiaro e conciso, soprattutto quando si verificano valori specifici dei campi.

struct Point {
  x: i32,
  y: i32,
}

fn main() {
  let p = Point { x: 0, y: 7 };

  match p {
    Point { x, y: 0 } => println!("On the X axis at {}", x),
    Point { x: 0, y } => println!("On the Y axis at {}", y),
    Point { x, y } => println!("Not on an axis: ({}, {})", x, y),
  }
}

Destrutturazione degli enum con dati

In Rust, gli enum possono contenere dati associati. Il pattern matching è il modo principale per estrarre questi dati da una variante di un enum.

È possibile destrutturare i dati direttamente in nuove variabili, semplificando l'utilizzo del contenuto di ogni variante.

enum Message {
  Quit,
  Move { x: i32, y: i32 },
  Write(String),
  ChangeColor(i32, i32, i32),
}

fn process_message(msg: Message) {
  match msg {
    Message::Quit => println!("Quit message."),
    Message::Move { x, y } => {
      println!("Move to x: {}, y: {}", x, y);
    }
    Message::Write(text) => println!("Text message: {}", text),
    Message::ChangeColor(r, g, b) => {
      println!("Color: R:{}, G:{}, B:{}", r, g, b);
    }
  }
}

fn main() {
  process_message(Message::Move { x: 10, y: 20 });
  process_message(Message::Write(String::from("Hello!")));
}

Il pattern jolly `_`

Il pattern speciale _ (underscore) funge da caso predefinito. Corrisponde a qualsiasi valore, senza associarlo a quel valore.

È utile quando è necessario coprire tutti i casi per garantire l'esaustività, ma il valore specifico corrispondente a un determinato braccio non è importante.

fn main() {
  let some_value = Some(5);
  let absent_value: Option<i32> = None;

  match some_value {
    Some(x) => println!("Got a value: {}", x),
    _ => println!("Something else!"), // Matches None too
  }

  match absent_value {
    Some(x) => println!("Got a value: {}", x),
    _ => println!("No value here!"),
  }
}

`if let` per pattern singoli

A volte interessa verificare un solo pattern specifico e ignorare tutti gli altri. In questi casi, if let è un'alternativa più concisa a un'espressione match completa.

In sostanza, significa: "se questo pattern corrisponde, esegui questa operazione; altrimenti, non fare nulla (oppure esegui un blocco else facoltativo)".

fn main() {
  let config_max = Some(3u8);
  let none_value: Option<u8> = None;

  if let Some(max) = config_max {
    println!("Max configured to be: {}", max);
  }

  if let Some(val) = none_value {
    println!("This won't print: {}", val);
  } else {
    println!("No value found!");
  }
}

`while let` per i cicli condizionali

Come if let, while let consente di eseguire un ciclo finché un pattern continua a corrispondere.

È estremamente utile per elaborare elementi di raccolte come Vec, quando si desidera continuare finché non rimangono più elementi corrispondenti (ad esempio, finché pop() non restituisce None).

fn main() {
  let mut stack = vec![1, 2, 3];

  while let Some(top) = stack.pop() {
    println!("Popped: {}", top);
  }

  println!("Stack is empty now.");
}

Guardie di match: aggiungere condizioni

È possibile aggiungere una condizione if aggiuntiva, chiamata guardia di match, a un braccio di match. Il pattern deve corrispondere E la condizione della guardia deve essere vera affinché quel braccio venga eseguito.

Questo consente un controllo più preciso all'interno di un pattern, senza dover creare altre varianti di enum.

fn main() {
  let num = Some(4);

  match num {
    Some(x) if x % 2 == 0 => println!("Even number: {}", x),
    Some(x) if x < 5 => println!("Small odd number: {}", x),
    Some(x) => println!("Any other number: {}", x),
    None => println!("No number"),
  }
}

Sfida sul pattern matching

Consideri il seguente frammento di codice Rust. Quali delle seguenti affermazioni sull'espressione match e sul suo output sono VERE?

enum Status {
  Loading,
  Success(u32),
  Error(String),
}

fn process_status(s: Status) {
  match s {
    Status::Success(code) if code > 200 => println!("Success with high code: {}", code),
    Status::Success(code) => println!("Success with code: {}", code),
    Status::Error(msg) => println!("Failed: {}", msg),
    _ => println!("Status unknown or loading..."),
  }
}

fn main() {
  process_status(Status::Success(201));
  process_status(Status::Error(String::from("Network issue")));
  process_status(Status::Loading);
  process_status(Status::Success(200));
}

Riepilogo: padroneggiare i pattern

Ha esplorato la straordinaria potenza del pattern matching in Rust! È un concetto fondamentale per scrivere codice chiaro, conciso e sicuro.

  • Le espressioni match forniscono un controllo esaustivo del flusso in base alla struttura dei dati.
  • È possibile verificare valori letterali, intervalli e usare pattern jolly (_).
  • La destrutturazione consente di estrarre direttamente valori da struct ed enum.
  • if let e while let offrono modalità concise per verificare singoli pattern.
  • Le guardie di match aggiungono logica condizionale ai bracci di match.

Continui a esercitarsi con questi pattern: sono essenziali per scrivere Rust idiomatico!

Gratis per iniziare

Impara Rust con un tutor IA — gratis

Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.

Corsi
39
Lezioni
144

Domande Frequenti

La lezione «Pattern matching avanzato» è gratuita?

Sì — il testo completo di «Pattern matching avanzato» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Learn Rust Coding, passa a CoddyKit PRO. Il corso Learn Rust Coding include 3 lezioni in totale.

Cosa imparerò in «Pattern matching avanzato»?

Padroneggi le espressioni `match` e altre forme di pattern matching per gestire le varianti dei dati in modo conciso ed esaustivo. Eserciti Learn Rust Coding con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Learn Rust Coding?

Non è richiesta alcuna esperienza precedente. Learn Rust Coding su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 3.

Quanto tempo richiede la lezione «Pattern matching avanzato»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Learn Rust Coding?

Sì. Ogni lezione Learn Rust Coding include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Definire e utilizzare le struct
  2. Enum per tipi personalizzati
  3. Pattern matching avanzato
← Torna a Learn Rust Coding