Ce face variabile și mutabilitate (let, mut)
let leagă o valoare de un nume. În Rust, variabilele sunt imuabile implicit: după let x = 5;, o atribuire x = 6; este eroare de compilare (E0384). Astfel vezi imediat, din declarație, care valori se schimbă în program.
Când ai nevoie să modifici valoarea, scrii let mut. Cuvântul mut apare și în referințe (&mut x), în parametri (mut v: Vec<i32>) și în tipare. Dacă pui mut la o variabilă pe care nu o modifici, compilatorul te avertizează.
Tipul se deduce de obicei din valoare; îl scrii când compilatorul nu are destule informații (let n: u32 = "7".parse().unwrap();). O variabilă poate fi declarată fără valoare și inițializată mai târziu, dar trebuie inițializată înainte de prima folosire.
Exemple
Exemplul 1: Variabilă imuabilă și variabilă mutabilă
nume rămâne la fel tot programul, deci nu are nevoie de mut. total se modifică în buclă, deci este declarat cu let mut.
fn main() {
let nume = "Ana";
let mut total = 0;
for nota in [9, 10, 8] {
total += nota;
}
println!("{nume} are în total {total} puncte");
}
Rezultat
Ana are în total 27 puncte
Exemplul 2: Ce se întâmplă dacă modifici o variabilă fără mut
Compilatorul refuză programul și spune exact ce să schimbi: let mut stoc = 10;.
fn main() {
let stoc = 10;
println!("Stoc inițial: {stoc}");
stoc = stoc - 3;
println!("Stoc după vânzare: {stoc}");
}
Mesajul compilatorului (programul nu se compilează)
error[E0384]: cannot assign twice to immutable variable `stoc`
--> main.rs:4:5
|
2 | let stoc = 10;
| ---- first assignment to `stoc`
3 | println!("Stoc inițial: {stoc}");
4 | stoc = stoc - 3;
| ^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
|
help: consider making this binding mutable
|
2 | let mut stoc = 10;
| +++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0384`.
Exemplul 3: Tip explicit, desfacere și inițializare întârziată
parse() poate produce multe tipuri, deci tipul u32 trebuie scris. let (oras, judet) = ... desface un tuplu. mesaj primește valoare o singură dată, pe una dintre ramuri, deci nu are nevoie de mut.
fn main() {
let locuitori: u32 = "271692".parse().unwrap();
let (oras, judet) = ("Iași", "IS");
let mesaj;
if locuitori > 200_000 {
mesaj = "oraș mare";
} else {
mesaj = "oraș mic";
}
println!("{oras} ({judet}): {locuitori} locuitori, {mesaj}");
}
Rezultat
Iași (IS): 271692 locuitori, oraș mare
Greșeli frecvente
- Uiți
mutși primeșticannot assign twice to immutable variable(E0384). Adaugămutdoar acolo unde valoarea chiar se schimbă. - Pui
mut„ca să fie”: compilatorul dă avertismentulvariable does not need to be mutable, iar cu-D warnings(cum sunt compilate exemplele de pe acest site) build-ul se oprește. - Confunzi
let mutcu shadowing:let x = x + 1;creează o variabilă nouă, nu o modifică pe cea veche. Vezi pagina despre shadowing. - Folosești o variabilă declarată cu
let x;înainte de a-i da valoare: eroarea E0381used binding isn't initialized.
Comenzi înrudite
shadowing (umbrirea variabilelor): Declari din nou o variabilă cu același nume: cea nouă o ascunde pe cea veche și poate avea chiar alt tip.const și static: const definește o valoare fixă calculată la compilare; static definește o variabilă globală cu o singură adresă, care trăiește tot programul.tipuri scalare (întregi, f64, bool, char): Tipurile de bază ale lui Rust: întregi cu și fără semn, numere cu virgulă, bool (true/false) și char (un caracter Unicode).borrowing și referințe (& și &mut): O referință (&) împrumută o valoare fără să o ia de la proprietar. Regula: oricâte referințe de citire SAU una singură de modificare.pattern matching (tipare): Tiparele descriu forma unei valori și scot din ea părțile de care ai nevoie: în let, match, if let, for și parametrii funcțiilor.