Sinora abbiamo sviluppato tutti i nostri programmi Rust all'interno del main
, la funzione che svolge il ruolo di entry point dell'esecuzione, il suo punto d'inizio, per così dire. Al di fuori del main
abbiamo sinora definito funzioni e struct
ma tutto era incluso all'interno di un unico file di estensione .rs
. Adesso però è giunto il momento di estendere i nostri orizzonti.
Da ora in poi avremo bisogno di sfruttare:
- moduli contributor
- librerie software
- dipendenze
Con questa lezione e quelle immediatamente successive, impareremo a gestire tutto questo e ciò ci permetterà di avere a disposizione gli strumenti per manovrare un vero flusso di lavoro da programmatore Rust.
I moduli in Rust
I moduli sono la componente fondamentale di tutta questa architettura e sono essenzialmente il modo che Rust offre per poter organizzare il codice suddividendolo in una gerarchia di unità, file e cartelle. Un altro aspetto fondamentale dei moduli consiste nella possibilità di gestire la visibilità delle componenti e ciò sarà basilare per definire cosa ha un ruolo "interno" al modulo e cosa è fatto per essere esportato.
Un esempio di modulo
Le parole chiave che ci accompagnano nell'utilizzo dei moduli sono essenzialmente tre:
mod
pub
pubbliciuse
conosciamo
Creiamo un modulo che contenga due funzioni, una chiamata saluta
che genera un messaggio di saluto ed un'altra, genera_saluto
, che crea la stringa di saluto in sé stessa: esempio dal bassissimo valore pratico ma estremamente importante a livello didattico!
mod modulo_saluto{
fn genera_saluto() -> &'static str {
"Ciao a tutti!"
}
pub fn saluta() -> String {
let mut saluto: String = "Messaggio: ".to_owned();
saluto.push_str(genera_saluto());
saluto
}
}
Notiamo che una delle due funzioni, saluta
pub
modulo_saluto::saluta
modulo_saluto
Le regole dei moduli valgono anche nello stesso file. Pertanto anche scrivendo di seguito il main
dovremo indicare il percorso completo della funzione:
fn main() {
println!("{}", modulo_saluto::saluta());
}
Il risultato dell'output sarà, come si può immaginare, Messaggio: Ciao a tutti!.
Utilizzo di use in Rust
Come accennato prima, use
è la parola chiave che permette di utilizzare un elemento interno di un modulo solo con il suo nome e senza l'intero percorso.
Ad esempio, in questo caso possiamo usare:
use modulo_saluto::saluta;
Per permettere al main
saluta
use modulo_saluto::saluta;
fn main() {
println!("{}", saluta());
}
Inoltre, use
può essere utilizzato con la parola chiave as
per indicare un nuovo nome che possiamo reputare più comodo e leggibile per l'elemento che stiamo importando:
use modulo_saluto::saluta as ciaociao;
fn main() {
println!("{}", ciaociao());
Dal momento in cui abbiamo definito ciaociao
saluta
ciaociao
alias
modulo_saluto::saluta
Si faccia attenzione che use
non serve a modificare la visibilità ma solo a fare in modo di poter chiamare componenti di un modulo usando semplicemente il loro nome. In pratica, quello che propone è un'integrazione dell'attuale spazio dei nomi che estende il set di funzionalità invocabili a disposizione della porzione di programma che stiamo scrivendo.