Funzioni
Abbiamo già incontrato la funzione main, che viene invocata all'inizio dell'esecuzione di ogni programma.
Possiamo definire altre funzioni tramite la parola chiave fn, e possono essere invocate da altre funzioni.
fn main() { println!("funzione main"); // chiama funzione stampa stampa(); } fn stampa() { println!("funzione stampa"); }
Se proviamo a eseguire questo programma ci viene restituito
funzione main
funzione stampa
Le funzioni possono prendere dei parametri in ingresso, in questo caso dobbiamo fornire i tipi dei parametri esplicitamente
fn main() { let x = 5; stampa_valore(x); } fn stampa_valore(valore: u32) { println!("Il valore è {valore}"); }
Il risultato di questo codice è
Il valore è 5
Valori di ritorno
Le funzioni possono ritornare dei valori, e il tipo di ritorno deve essere annotato esplicitamente con la notazione ->.
fn main() { let x = 5; let y = 6; let somma = calcola_somma(x, y); println!("La somma di {} e {} è {}", x, y, somma); } fn calcola_somma(x: i32, y: i32) -> i32 { x + y }
Il risultato dell'esecuzione di questo codice è
La somma di 5 e 6 è 11
Questo codice potrebbe sembrare strano perché non ci sono istruzioni di tipo return.
Di fatto, in Rust è presente questa istruzione e la funzione sopra è equivalente a questa:
#![allow(unused)] fn main() { fn calcola_somma(x: i32, y: i32) -> i32 { return x + y; } }
Ma sopra stiamo utilizzando il fatto che le funzioni in Rust ritornano implicitamente il valore dell'ultima espressione (senza il punto e virgola). Questa è una feature anche presente nei blocchi, per esempio
fn main() { let a = { let x = 4; x * 3 }; println!("a: {a}"); // => a: 12 }
Quello che sta accadendo è che stiamo definendo un nuovo blocco tra parentesi graffe, e il risultato della valutazione del blocco è implicitamente l'ultima espressione senza il punto e virgola finale.
Le classiche regole di scoping vengono applicate, quindi al di fuori del blocco la variabile x non può essere acceduta.
Vedremo nel prossimo capitolo che il passaggio di variabili da uno scope all'altro in Rust avviene in maniera particolare.