Скоупы
В Rust время жизни переменной ограничено скоупом — блоком из фигурных скобок, в котором она объявлена. По завершению скоупа все переменные, объявленные в нём, автоматически удаляются.
fn main() {
let a = 1;
{
let b = 2;
// В этом месте существуют и a, и b
} // Выход из скоупа: b удаляется
// В этом месте существует только a
let c = 3;
} // Выход из скоупа: a и c удаляются
Значение скоупа
В Rust каждый скоуп возвращает значение. Это значит, что результат скоупа можно присвоить переменной. Само же значение, возвращаемое скоупом — это последнее значение, вычисленное в скоупе.
#![allow(unused)]
fn main() {
let a: i32 = {
let x = 1;
let y = 2;
x + y // последнее вычисленное выражение
};
println!("{a}"); // 3
}
Будьте внимательны: чтобы результат последнего выражения стал результатом скоупа, после него не должно быть точки с запятой.
Дело в том, что в отличие от C, где ; означает конец текущего выражения, в Rust ; служит разделителем между выражениями. То есть, например, выражение
{ a; }
трактуется как
{ a; () }
и, следовательно, результат всего скоупа будет — Unit, а не a.
Вот так будет выглядеть пример выше, если по ошибке поставить ; в конце скоупа.
#![allow(unused)]
fn main() {
let a: () = {
let x = 1;
let y = 2;
x + y;
};
}
Тот факт, что скоуп возвращает значение, используется в ряде других конструкций, о которых мы поговорим далее.