Cieniowanie to możliwość wielokrotnego deklarowania zmiennej o tej samej nazwie w tej samej przestrzeni nazw, przy czym nowa zmienna "cienia" poprzednią. W językach bez cieniowania (C, C++) powtórna definicja zmiennej prowadzi do błędu lub nieokreślonego zachowania. Rust pozwala na cieniowanie, a każda zmienna jest niezależnym obiektem z nowym typem lub wartością. Jest to wygodne przy krokowych transformacjach wartości — na przykład, można od razu przerobić ciąg na liczbę, nie wymyślając nowych nazw.
Problem: z jednej strony — poprawa czytelności, zapobieganie rozdmuchiwaniu nazw zmiennych; z drugiej — trudności w debugowaniu, jeśli przypadkowo "cieniujemy" zmienną w złożonym bloku i uzyskujemy nieoczekiwany wynik.
Rozwiązanie: Cieniowanie stosuje się tylko tam, gdzie rzeczywiście ułatwia transformację i nie pogarsza czytelności. Każde "let var = ...;" tworzy nową zmienną, stara pozostaje niezmieniona poza blokiem deklaracji.
Przykład kodu:
fn example() { let x = "42"; let x = x.parse::<i32>().unwrap(); println!("x: {}", x); // x: 42 }
Kluczowe cechy:
Czy cieniowanie może zmieniać mutowalność zmiennej?
Tak, można "cieniować" zmienną niemutowalną zmienną mutowalną i odwrotnie:
let x = 5; let mut x = x; x += 1;
Czy oznacza to, że poprzednia zmienna została zniszczona?
Nie, wartości poprzedniej zmiennej żyją do końca bloku, w którym zostały zadeklarowane, ale stają się niedostępne przez nazwę.
Czy można używać cieniowania wewnątrz pętli lub wewnątrz zagnieżdżonych bloków?
Tak, każda przestrzeń nazw (scope) pozwala na deklarowanie zmiennych o tych samych nazwach, a to różne zmienne.
W funkcji jest let result = expr1; ... let result = expr2;, gdzie typy się różnią.
Zalety:
Wady:
Cieniowanie używane jest tylko do zmiany typu: najpierw analizowany jest ciąg, a następnie następuje przypisanie liczby.
Zalety:
Wady: