Rust è un linguaggio di programmazione per sistemi moderno, progettato per prestazioni, sicurezza e concorrenza. Fornisce agli utenti potenti caratteristiche linguistiche, cercando di eliminare errori di programmazione comuni, come dereferenziazioni di puntatori nulli e condizioni di gara sui dati. Rust enfatizza astrazioni a costo zero, consentendo agli sviluppatori di scrivere codice di alto livello senza sacrificare le prestazioni. È particolarmente adatto per compiti in cui è necessario un controllo a basso livello dell'hardware e della gestione della memoria, come la programmazione di sistemi, il web assembly e la creazione di applicazioni ad alte prestazioni.
Rust è stato concepito nel 2006 da Graydon Hoare presso Mozilla Research. L'obiettivo iniziale del linguaggio era affrontare le sfide dello sviluppo di software concorrente sicuro e creare un'alternativa più affidabile ai linguaggi di programmazione di sistemi esistenti. Nel 2010, è stata rilasciata la prima versione pubblica di Rust, che ha rapidamente attirato l'attenzione per il suo approccio innovativo alla sicurezza della memoria e alla concorrenza.
Rust trae ispirazione da diversi linguaggi di programmazione, come C++ per il suo design orientato alle prestazioni e i linguaggi di programmazione funzionale per la sua enfasi sull'immutabilità e sulle astrazioni potenti. Il suo design riflette anche principi di linguaggi come Haskell, in particolare nel suo robusto sistema di tipi e nelle capacità di pattern matching.
Dalla sua nascita, Rust è maturato in un linguaggio ampiamente riconosciuto, con una forte comunità di sviluppatori e un ecosistema di librerie in crescita. Il linguaggio è stato ufficialmente supportato da Mozilla e ha guadagnato terreno in vari ambiti, tra cui lo sviluppo web, i sistemi embedded e lo sviluppo di giochi. Il rilascio di Rust 1.0 nel 2015 ha segnato una pietra miliare significativa, consolidando la sua stabilità e prontezza per l'uso in produzione. La Rust Foundation, istituita nel 2021, supporta il suo continuo sviluppo e governance.
Il modello di proprietà unico di Rust consente agli sviluppatori di gestire la memoria senza un garbage collector. Ogni variabile in Rust ha un unico proprietario, e la proprietà può essere trasferita o "presa in prestito" tramite riferimenti. Questa caratteristica aiuta a garantire la sicurezza della memoria imponendo regole di prestito rigorose.
fn main() {
let s1 = String::from("Ciao");
let s2 = &s1; // Prestito di s1
println!("{}", s2);
}
Il pattern matching in Rust consente agli sviluppatori di destrutturare i tipi di dati e gestire il flusso di controllo complesso senza problemi. L'istruzione match
fornisce un modo potente per ramificare la logica in base ai pattern di valore.
fn main() {
let number = 4;
match number {
1 => println!("Uno"),
2 => println!("Due"),
_ => println!("Altro"),
}
}
Rust utilizza l'inferenza dei tipi, consentendo al compilatore di dedurre automaticamente i tipi delle variabili, semplificando il codice e migliorando la leggibilità.
fn main() {
let x = 5; // Il compilatore deduce che x è di tipo i32
}
I trait sono simili alle interfacce in altri linguaggi e consentono il polimorfismo. Definiscono comportamenti condivisi che i tipi possono implementare.
trait Speak {
fn speak(&self);
}
struct Dog;
impl Speak for Dog {
fn speak(&self) {
println!("Bau!");
}
}
I tipi Option
e Result
di Rust forniscono robusti paradigmi di gestione degli errori e programmazione sicura rispetto ai null, consentendo agli sviluppatori di esprimere esplicitamente la possibilità di assenza o errore.
fn divide(x: f64, y: f64) -> Option<f64> {
if y == 0.0 {
None
} else {
Some(x / y)
}
}
Rust supporta la concorrenza senza paura attraverso il suo sistema di proprietà, consentendo a più thread di operare sui dati con un rischio minimo di condizioni di gara.
use std::thread;
fn main() {
let handle = thread::spawn(|| {
println!("Ciao da un thread!");
});
handle.join().unwrap();
}
Il sistema di macro di Rust consente la generazione di codice, rendendo possibile scrivere costrutti sintattici personalizzati che possono essere riutilizzati in tutto il codice.
macro_rules! say_hello {
() => {
println!("Ciao!");
};
}
fn main() {
say_hello!();
}
Le closures in Rust sono funzioni anonime che possono catturare variabili dal loro ambiente, rendendole flessibili per paradigmi di programmazione funzionale.
fn main() {
let add = |a, b| a + b;
println!("{}", add(5, 7));
}
Rust utilizza un sistema di moduli per organizzare il codice e controllare la visibilità. I crate sono pacchetti di codice Rust che possono essere condivisi e riutilizzati.
mod my_module {
pub fn hello() {
println!("Ciao da my_module!");
}
}
fn main() {
my_module::hello();
}
Rust ha funzionalità di documentazione integrate, e lo strumento Rustdoc genera automaticamente documentazione dai commenti nel codice sorgente.
/// Questa funzione somma due numeri.
///
/// # Esempi
///
/// ```
/// let result = add(2, 3);
/// assert_eq!(result, 5);
/// ```
fn add(a: i32, b: i32) -> i32 {
a + b
}
Rust ha un ricco set di strumenti per sviluppatori, incluso il suo gestore di pacchetti, Cargo, che facilita la gestione delle dipendenze, la costruzione e la pubblicazione di librerie e applicazioni. La libreria standard di Rust fornisce un ampio supporto runtime per vari compiti.
Diverse IDE e editor supportano lo sviluppo in Rust, tra cui:
Per creare un nuovo progetto Rust, gli sviluppatori possono utilizzare Cargo con il seguente comando:
cargo new my_project
Questo comando genera una nuova directory contenente una struttura di progetto Rust di base. Per costruire il progetto, basta navigare nella directory del progetto e eseguire:
cargo build
Rust è utilizzato in vari ambiti grazie alle sue caratteristiche di prestazioni e sicurezza. Le principali applicazioni includono:
Rust è spesso confrontato con altri linguaggi di programmazione di sistemi a causa della sua enfasi su prestazioni e sicurezza. Ecco alcuni confronti:
Tradurre codice Rust in altri linguaggi può essere impegnativo a causa del suo modello di proprietà unico e delle sue caratteristiche avanzate. Tuttavia, alcuni strumenti facilitano le traduzioni da codice a codice, come: