Lo shadowing è la possibilità di dichiarare più volte una variabile con lo stesso nome all'interno dello stesso ambito visivo, dove la nuova variabile "oscurerà" la precedente. Nei linguaggi senza shadowing (C, C++) la ridichiarazione di una variabile porta a un errore o a un comportamento indefinito. Rust consente il shadowing e ogni variabile diventa un oggetto indipendente con un nuovo tipo o valore. Questo è comodo per trasformazioni passo-passo di valori — ad esempio, convertire una stringa in un numero senza dover inventare nuovi nomi.
Problema: da un lato — miglioramento della leggibilità, prevenendo l'ingrossamento dei nomi delle variabili; dall'altro — difficoltà nel debug se accidentalmente si "oscura" una variabile in un blocco complesso e si ottiene un risultato inatteso.
Soluzione: lo shadowing deve essere utilizzato solo dove facilita effettivamente la trasformazione e non peggiora la leggibilità. Ogni "let var = ...;" crea una nuova variabile, mentre la vecchia rimane invariata al di fuori del blocco di dichiarazione.
Esempio di codice:
fn example() { let x = "42"; let x = x.parse::<i32>().unwrap(); println!("x: {}", x); // x: 42 }
Caratteristiche chiave:
Può lo shadowing cambiare la mutabilità di una variabile?
Sì, è possibile "oscurare" una variabile immutabile con una mutabile e viceversa:
let x = 5; let mut x = x; x += 1;
Significa lo shadowing che la variabile precedente è stata distrutta?
No, i valori della variabile precedente vivono fino alla fine del blocco in cui sono stati dichiarati, ma diventano inaccessibili per nome.
È possibile utilizzare lo shadowing all'interno di un ciclo o all'interno di blocchi annidati?
Sì, ciascun ambito visivo consente di dichiarare variabili con lo stesso nome e queste sono variabili diverse.
Nella funzione c'è let result = expr1; ... let result = expr2;, dove i tipi differiscono.
Pro:
Contro:
Lo shadowing è usato solo per cambiare tipo: prima si analizza una stringa, poi si assegna un valore numerico.
Pro:
Contro: