Passer au contenu principal
eLearner.app
Module 2 · Leçon 2 sur 24/14 dans le cours~15 min
Leçons du module (2/2)

Pattern matching, Option e Result

Rust possiede un meccanismo di controllo del flusso estremamente potente chiamato pattern matching. Permette di confrontare un valore con una serie di pattern ed eseguire codice in base al pattern corrispondente.

L'Istruzione match

L'istruzione match in Rust è simile allo switch in altri linguaggi, ma molto più potente e sicura. Il compilatore garantisce che il matching sia esaustivo, ossia che tutti i possibili casi siano gestiti:

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

let dir = Direction::East;

match dir {
    Direction::North => println!("Andiamo a Nord"),
    Direction::South => println!("Andiamo a Sud"),
    Direction::East => println!("Andiamo a Est"),
    Direction::West => println!("Andiamo a Ovest"),
}

Gestire l'assenza di valore: Option

Rust non ha il concetto di valore nullo (null o nil). Al suo posto, la libreria standard definisce un enum chiamato Option<T> che può contenere:

  • Some(T): contiene un valore di tipo T.
  • None: indica l'assenza di valore.
Code
let x: Option<i32> = Some(5);
let y: Option<i32> = None;

match x {
    Some(val) => println!("C'e un valore: {}", val),
    None => println!("Nessun valore trovato"),
}

Gestire gli errori ripristinabili: Result

Per operazioni che possono fallire (come la lettura di un file o la conversione di una stringa in numero), Rust usa l'enum Result<T, E> che possiede due varianti:

  • Ok(T): l'operazione è andata a buon fine e contiene il valore di successo T.
  • Err(E): l'operazione è fallita e contiene l'errore E.
Code
fn divide(numerator: f64, denominator: f64) -> Result<f64, String> {
    if denominator == 0.0 {
        Err(String::from("Divisione per zero!"))
    } else {
        Ok(numerator / denominator)
    }
}

Grazie al compilatore di Rust, sei obbligato a gestire il caso Err prima di poter accedere al valore dentro Ok, evitando moltissimi bug a runtime.

Il Pattern Jolly _ (Wildcard)

Quando lavoriamo con tipi di dato che hanno un gran numero di varianti (come gli interi), elencare tutti i casi in un match è impossibile. Rust permette di usare il carattere jolly _ per catturare tutti i casi rimanenti non definiti esplicitamente:

Code
let some_u8 = 3u8;
match some_u8 {
    1 => println!("Uno"),
    2 => println!("Due"),
    _ => println!("Qualcos'altro"), // Gestisce tutti gli altri valori
}

Prova tu

Exercice#rust.m2.l2.e1
Tentatives : 0Chargement…

Dichiara una variabile maybe_value di tipo Option<i32> contenente Some(42). Usa un'istruzione match su maybe_value: se contiene Some(v) stampa 'value is: v' (con println!), se contiene None stampa 'no value'.

Chargement de l'éditeur…
Afficher l'indice

Scrivi un blocco `match maybe_value { Some(v) => println!('value is: {}', v), None => println!('no value') }`.

Solution disponible après 3 tentatives

Exercice#rust.m2.l2.e2
Tentatives : 0Chargement…

Completa la funzione check_age in modo che restituisca Ok('Adult') se age è maggiore o uguale a 18, oppure Err('Minor') in caso contrario.

Chargement de l'éditeur…
Afficher l'indice

Usa un `if age >= 18`per decidere se restituire`Ok('Adult')`oppure`Err('Minor')`.

Solution disponible après 3 tentatives

Exercice#rust.m2.l2.e3
Tentatives : 0Chargement…

Dichiara un enum chiamato Status contenente le varianti Active e Inactive. Nel main, dichiara una variabile current_status con valore Status::Active. Infine, usa un'istruzione match su current_status per stampare 'active' se lo stato è Active, o 'inactive' se lo stato è Inactive.

Chargement de l'éditeur…
Afficher l'indice

Definisci l'enum prima del main con `enum Status { Active, Inactive }`. Nel main usa `let current_status = Status::Active;`ed esegui il`match` sulle varianti.

Solution disponible après 3 tentatives