Salta ai contenuti

Sintassi di Rust

Ora che sai eseguire Rust, rallentiamo un attimo e guardiamo cosa significa davvero ogni parte di un programma. Useremo l’esempio più piccolo possibile e lo smonteremo pezzo per pezzo.

fn main() {
println!("Ciao, mondo!");
}

Output:

Ciao, mondo!
▶ Provalo tu
fn main() {
// qui viene eseguito il tuo codice
}

Ogni programma Rust comincia da una funzione chiamata main. Quando esegui il programma, Rust cerca main ed esegue il codice al suo interno.

  • fn è la parola chiave per definire una funzione (un blocco di codice con un nome).
  • main è il nome della funzione: proprio questo nome è speciale, perché è il punto d’ingresso.
  • () contiene gli input della funzione (qui è vuoto: main non ne riceve).
  • Le parentesi graffe { } racchiudono il corpo, cioè il codice che appartiene alla funzione.

Dentro il corpo, ogni comando di solito è un’istruzione (statement), e le istruzioni finiscono con un punto e virgola ;:

fn main() {
let x = 5;
let y = 10;
println!("{}", x + y);
}

Output:

15
▶ Provalo tu

Dimenticare un punto e virgola dove serve è uno degli errori più comuni dei principianti, e il compilatore te lo indicherà con precisione.

Il codice Rust è fatto di due tipi di pezzi, e la differenza conta più in Rust che nella maggior parte dei linguaggi:

  • Un’istruzione (statement) fa qualcosa ma non restituisce un valore. let x = 5; è un’istruzione.
  • Un’espressione produce un valore. 5, x + 1 e x * 2 sono tutte espressioni.

Ecco la parte che sorprende: anche un blocco di codice tra parentesi graffe { } è un’espressione. Il suo valore è l’ultima riga, scritta senza punto e virgola:

fn main() {
let x = 5;
let y = {
let doubled = x * 2; // un'istruzione dentro il blocco
doubled + 1 // niente punto e virgola: questo è il valore del blocco
};
println!("y vale {y}");
}

Output:

y vale 11
▶ Provalo tu

Il blocco esegue le sue istruzioni, poi restituisce doubled + 1, cioè 11, che diventa y. Nota il punto e virgola dopo la } di chiusura: l’intera riga let y = ...; resta comunque un’istruzione.

Se aggiungi un punto e virgola dopo doubled + 1, quella riga smette di essere il valore del blocco. Il blocco allora restituisce «niente» (Rust lo scrive ()), e println! non può stamparlo, quindi il codice non compila. Questa regola del «niente punto e virgola sull’ultima riga» è proprio il modo in cui le funzioni restituiscono i valori. La rivedrai nella pagina Funzioni e con if usato come espressione.

Guarda bene println!: quel punto esclamativo non è un errore di battitura. Il ! significa che è una macro, non una funzione normale.

Non devi ancora capire a fondo le macro. Ti basta sapere questo: quando vedi !, è una macro. Per ora l’unica che userai è println! per stampare testo.

fn main() {
println!("Questa è la chiamata di una macro");
}

Dentro println!, le parentesi graffe {} sono segnaposto che vengono riempiti con i valori che passi dopo il testo:

fn main() {
let name = "Ferris";
let age = 10;
println!("{} ha {} anni", name, age);
}

Output:

Ferris ha 10 anni
▶ Provalo tu

Puoi anche mettere il nome della variabile direttamente dentro le graffe, che spesso è più pulito:

println!("{name} ha {age} anni");

A Rust non importa dell’indentazione come a Python: usa le parentesi graffe { } per capire dove iniziano e finiscono i blocchi. L’indentazione serve solo agli esseri umani per leggere il codice più facilmente.

Detto questo, la comunità ha uno stile standard, e Rust include uno strumento che lo applica automaticamente:

Terminal window
cargo fmt

Eseguire cargo fmt riformatta il tuo codice nello stile ufficiale. Prendi l’abitudine di usarlo.

Puoi lasciare nel codice delle note che Rust ignora. Sono i commenti, e cominciano con //:

fn main() {
// Questo è un commento: Rust lo salta
println!("Ciao!"); // i commenti possono stare anche in fondo a una riga
}

Parleremo dei commenti più in dettaglio nella prossima pagina.

Crea due variabili, a = 7 e b = 3, e stampa 7 + 3 = 10. Lascia che sia Rust a fare la somma. Suggerimento: un println! può avere più segnaposto {}, riempiti in ordine dai valori dopo il testo.

Mostra la soluzione
fn main() {
let a = 7;
let b = 3;
println!("{} + {} = {}", a, b, a + b);
}

Output:

7 + 3 = 10
▶ Provalo tu

Un negozio vende 3 articoli a 4 l’uno, più 2 di spedizione. Calcola total con un blocco { }: al suo interno crea un subtotal, poi restituisci subtotal + 2. Stampa Totale: 14. Suggerimento: l’ultima riga del blocco non deve avere il punto e virgola.

Mostra la soluzione
fn main() {
let price = 4;
let quantity = 3;
let total = {
let subtotal = price * quantity;
subtotal + 2 // spedizione
};
println!("Totale: {total}");
}

Output:

Totale: 14
▶ Provalo tu
  • Ogni programma comincia dalla funzione main.
  • Il codice sta dentro le parentesi graffe { }; la maggior parte delle istruzioni finisce con ;.
  • Le istruzioni fanno qualcosa; le espressioni producono un valore. L’ultima riga di un blocco senza ; è il suo valore.
  • Un ! (come in println!) significa che è una macro.
  • Le {} dentro println! sono segnaposto riempiti dai valori che passi.
  • L’indentazione serve alla leggibilità: lancia cargo fmt per formattare in automatico.

Verifica veloce

1. Cosa ha di speciale la funzione main in un programma Rust?

2. Cosa significa il ! dopo println?

3. Quanto vale y dopo let y = { let a = 2; a + 1 };?

Punteggio: 0 / 3