Saltar al contenido principal
eLearner.app
Módulo 5 · Lección 1 de 29/14 en el curso~12 min
Lecciones del módulo (1/2)

Generici e funzioni

I generics (tipi generici) consentono di scrivere codice flessibile e riutilizzabile, evitando la duplicazione di logica per tipi di dati differenti. Invece di definire più funzioni o strutture per tipi diversi (come i32, f64, o String), possiamo usare un parametro di tipo generico, convenzionalmente indicato con la lettera T.

Il compilatore Rust gestisce i generics tramite un processo chiamato monomorfizzazione: durante la compilazione, il compilatore genera una copia del codice generico per ciascun tipo concreto con cui viene effettivamente utilizzato. In questo modo non c'è alcun sovraccarico di prestazioni a runtime.


Funzioni Generiche

Per definire una funzione generica, inseriamo il parametro di tipo <T> subito dopo il nome della funzione e prima dell'elenco dei parametri:

Code
fn print_value<T: std::fmt::Debug>(value: T) {
    println!("Valore: {:?}", value);
}

Nelle funzioni generiche, possiamo usare il tipo generico T sia per i tipi degli argomenti che per il tipo di ritorno:

Code
fn identity<T>(value: T) -> T {
    value
}

Strutture Generiche

Possiamo utilizzare i parametri di tipo generico anche all'interno delle strutture dati (struct) per definire campi flessibili:

Code
struct KeyValuePair<K, V> {
    key: K,
    value: V,
}

fn main() {
    let pair = KeyValuePair {
        key: String::from("eta"),
        value: 30,
    };
}

Nel blocco impl per una struct generica, dobbiamo dichiarare il parametro di tipo <T> subito dopo la parola chiave impl per indicare che stiamo implementando metodi su una struttura generica:

Code
struct Container<T> {
    value: T,
}

impl<T> Container<T> {
    fn new(value: T) -> Self {
        Container { value }
    }

    fn value(&self) -> &T {
        &self.value
    }
}

Prova tu

Esercizio 1: La struttura Point

Ejercicio#rust.m5.l1.e1
Intentos: 0Cargando...

Definisci una struttura generica chiamata Point<T> con due campi: x di tipo T e y di tipo T. Nel main, istanzia una variabile point contenente un Point con valori x pari a 5 e y pari a 10 (interi), quindi stampa a schermo il valore di point.x.

Cargando editor...
Mostrar pista

Dichiara la struct usando `struct Point<T> { x: T, y: T }`. Istanziala nel main e usa `point.x` per stamparla.

Solución disponible después de 3 intentos

Esercizio 2: Inversione di una Tupla con swap

Ejercicio#rust.m5.l1.e2
Intentos: 0Cargando...

Scrivi una funzione generica chiamata swap<T> che accetta in input una tupla di due elementi (T, T) e restituisce una nuova tupla (T, T) con gli elementi invertiti di posizione. Nel main, chiama la funzione con la tupla (1, 2) e stampa il risultato.

Cargando editor...
Mostrar pista

La firma della funzione deve essere `fn swap<T>(pair: (T, T)) -> (T, T)`. Restituisci la tupla invertita con `(pair.1, pair.0)`.

Solución disponible después de 3 intentos

Esercizio 3: La struttura Container

Ejercicio#rust.m5.l1.e3
Intentos: 0Cargando...

Definisci una struct generica Container<T> contenente un campo value di tipo T. Implementa un blocco impl generico per definire un metodo new che accetta un valore di tipo T e restituisce un'istanza di Container<T>.

Cargando editor...
Mostrar pista

Usa `impl<T> Container<T>`per implementare il metodo associato`fn new(value: T) -> Self { Container { value } }`.

Solución disponible después de 3 intentos