Menu
Coddy logo textTech

Funzioni generiche

Fa parte della sezione Programmazione orientata agli oggetti del percorso Rust di Coddy. Lezione 27 di 61.

I generici non sono limitati alle struct. Puoi anche scrivere funzioni indipendenti che funzionano con qualsiasi tipo. Questo è utile quando ti serve una funzione di utilità che non appartiene a una struct specifica ma dovrebbe comunque essere flessibile.

La sintassi rispecchia quella che hai visto con le struct. Dichiara il parametro generico tra parentesi angolari dopo il nome della funzione, poi usalo nei parametri e nel tipo restituito:

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

Questa funzione identity accetta un valore di qualsiasi tipo e lo restituisce invariato. <T> dichiara il tipo generico, value: T lo accetta come parametro e -> T specifica il tipo restituito. Quando chiami la funzione, Rust deduce il tipo concreto:

let num = identity(42);        // T è i32
let text = identity("hello");  // T è &str

Puoi anche usare più parametri generici nelle funzioni, proprio come con le struct:

fn make_pair<T, U>(first: T, second: U) -> (T, U) {
    (first, second)
}

let pair = make_pair(10, "ten");  // restituisce (i32, &str)

Le funzioni generiche ti permettono di scrivere una logica riutilizzabile una sola volta e applicarla a molti tipi, riducendo la duplicazione del codice e mantenendo la sicurezza dei tipi.

challenge icon

Sfida

Facile

Costruiamo un modulo di utilità con funzioni generiche che possono funzionare con qualsiasi tipo! Creerai funzioni autonome che mostrano come i generici rendano il tuo codice flessibile e riutilizzabile, senza vincolarlo a una struttura specifica.

Organizzerai il codice in due file:

  • utils.rs: crea una raccolta di funzioni di utilità generiche pubbliche:
    • wrap_in_pair<T>: accetta un singolo valore e restituisce una tupla contenente due volte quel valore: (value, value). Il tipo deve implementare Clone, quindi usa <T: Clone>
    • swap<T, U>: accetta due valori potenzialmente di tipi diversi e li restituisce in ordine inverso come tupla (U, T)
  • main.rs: importa il tuo modulo di utilità e mostra queste funzioni generiche all'opera con tipi diversi. Mostra come le stesse definizioni di funzione gestiscono senza problemi interi, numeri a virgola mobile e stringhe.

Nel tuo file principale, mostra le tue funzioni di utilità:

  1. Usa wrap_in_pair con un intero (primo input, analizzato come i32) e stampa entrambi gli elementi
  2. Usa wrap_in_pair con una stringa (secondo input) e stampa entrambi gli elementi
  3. Usa swap con un intero (terzo input, analizzato come i32) e una stringa (quarto input), quindi stampa il risultato scambiato

Il tuo output deve rispettare questo formato:

Pair of ints: ({value}, {value})
Pair of strings: ({value}, {value})
Swapped: ({string}, {int})

Per esempio, con gli input 5, hello, 42 e world:

Pair of ints: (5, 5)
Pair of strings: (hello, hello)
Swapped: (world, 42)

Nota come wrap_in_pair funzioni in modo identico sia con gli interi sia con le stringhe, e come swap gestisca due tipi completamente diversi: questa è la flessibilità delle funzioni generiche!

Riceverai quattro input: un intero, una stringa, un altro intero e un'altra stringa.

Provalo tu

mod utils;

use std::io;

fn main() {
    // Leggi i quattro input
    let mut input1 = String::new();
    io::stdin().read_line(&mut input1).expect("Failed to read line");
    let num1: i32 = input1.trim().parse().expect("Invalid integer");

    let mut input2 = String::new();
    io::stdin().read_line(&mut input2).expect("Failed to read line");
    let str1 = input2.trim().to_string();

    let mut input3 = String::new();
    io::stdin().read_line(&mut input3).expect("Failed to read line");
    let num2: i32 = input3.trim().parse().expect("Invalid integer");

    let mut input4 = String::new();
    io::stdin().read_line(&mut input4).expect("Failed to read line");
    let str2 = input4.trim().to_string();

    // TODO: Usa wrap_in_pair con num1 e stampa il risultato
    // Formato: Pair of ints: ({value}, {value})

    // TODO: Usa wrap_in_pair con str1 e stampa il risultato
    // Formato: Pair of strings: ({value}, {value})

    // TODO: Usa swap con num2 e str2, poi stampa il risultato dopo lo scambio
    // Formato: Scambiati: ({string}, {int})
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Rust online