Главная / Курсы / Rust / Объявление и использование переменных
# Глава 2. Объявление и использование переменных Тип переменной в Rust определяется при объявлении и не может быть изменен впоследствии. С другой стороны в языке имеется возможность затенения переменных, то есть объявление одноименной переменной в той же области видимости. ## Объявление переменных Синтаксис объявления переменной: ``` let [mut] <variable name> [: type] [= variable value]; ``` Имена переменных [принято](https://rust-lang.github.io/api-guidelines/naming.html) писать в стиле `snake_case`: ```rust let my_var = 7; ``` По умолчанию (без ключевого слова `mut`) все переменные в Rust являются **неизменяемыми**. Неизменяемость переменных — это полезная особенность языка, позволяющая писать более надежный код. Не пренебрегайте этой особенностью. Для того чтобы сделать переменную изменяемой, необходимо добавить ключевое слово `mut`. Пример: ```rust let mut m = 7; m += 2; ``` Макрос `assert` проверяет истинность выражения: если выражение истинно, то программа выполняется дальше. В противном случае программа аварийно завершается с сообщением об ошибке. Код в данной задаче содержит синтаксическую ошибку, необходимо ее исправить: {.task_text} ```rust {.task_source #rust_chapter_0020_task_0010} let m = 3; m = m + 2; println!("m = {}", m); assert!(m == 5); ``` Переменную `m` необходимо сделать изменяемой. {.task_hint} ```rust {.task_answer} let mut m = 3; m = m + 2; println!("m = {}", m); assert!(m == 5); ``` В Rust можно не указывать тип переменной. В большинстве случаев компилятор определит тип переменной из контекста. Объявление `let n = 5` говорит компилятору, что переменная `n` имеет целочисленный тип `i32`. Но такая краткая запись не всегда возможна. Нередко требуется указывать конкретный тип переменной. Важно учитывать, что Rust не разрешает использовать неинициализированные переменные. Это позволяет избежать целый класс ошибок, связанных с использованием неинициализированных переменных. Переменную можно объявить без инициализации, но перед первым использованием такая переменная должна быть обязательно проинициализирована. Исправьте этот код, присвоив значение 0 переменной `counter` до первого ее использования: {.task_text} ```rust {.task_source #rust_chapter_0020_task_0020} let mut counter: u32; counter += 1; println!("counter = {}", counter); assert!(counter == 1); ``` Проще всего инициализировать переменную `counter` при создании. {.task_hint} ```rust {.task_answer} let mut counter: u32 = 0; counter += 1; println!("counter = {}", counter); assert!(counter == 1); ``` Обратите внимание, что язык позволяет инициализировать переменную в том месте, где она потребуется, а не сразу при объявлении: ```rust {.example_for_playground .example_for_playground_001} let dif: i32; let dec: i32 = 10; let sub: i32 = 3; dif = dec - sub; println!("dif = {}", dif); ``` Rust выдает предупреждение для неиспользуемых переменных. Такое предупреждение возможно отключить (хоть и нежелательно), либо начать название переменной с символа подчеркивания `_`. Исправьте этот код, чтобы избавиться от предупреждения: {.task_text} ```rust {.task_source #rust_chapter_0020_task_0030} let unused = 42; ``` Необходимо добавить знак подчеркивания в начало имени переменной. {.task_hint} ```rust {.task_answer} let _unused = 42; ``` ## Область видимости и затенение переменных {#block-shadowing} Область видимости переменной ограничена блоком, в котором эта переменная определена. Блок — это набор инструкций, заключенный между фигурными скобками `{}`. Переменная видна в блоке объявления и во всех вложенных блоках. Переменные, объявленные с помощью `let`, не могут находиться в глобальной области видимости: ```rust {.example_for_playground .example_for_playground_002} let value = 42; fn main() { println!("{value}"); } ``` [Функция `main()`](/courses/rust/chapters/rust_chapter_0020/) является точкой входа программы и находится в глобальной области видимости. Объявление переменной `value` на этом же уровне приведет к ошибке компиляции: ``` 1 | let value = 42; | ^^^ consider using `const` or `static` instead of `let` for global variables ``` Глобальные переменные стоит избегать по возможности. Про статические переменные будет рассказано в следующих главах. Требуется вычислить сумму переменных `external` и `internal`. Сейчас код содержит ошибку, нужно его исправить. При этом переменные `external` и `sum` должны остаться во внешнем блоке, а переменная `internal` во внутреннем блоке кода: {.task_text} ```rust {.task_source #rust_chapter_0020_task_0040} let external = 2; let sum; { let internal = 40; } sum = external + internal; println!("sum = {}", sum); assert!(sum == 42); ``` Сумму нужно вычислять в области видимости переменной `internal`, при этом переменная `internal` должна оставаться во внутреннем блоке. {.task_hint} ```rust {.task_answer} let external = 2; let sum; { let internal = 40; sum = external + internal; } println!("sum = {}", sum); assert!(sum == 42); ``` В Rust есть возможность определять переменные с одинаковыми именами в одной области видимости. Это называется **затенением переменных** (shadowing). Переменная с таким же именем затеняет собой предыдущую. В примере ниже строковая переменная `count` затеняется целочисленной: ```rust {.example_for_playground .example_for_playground_003} let count = "123"; let count: i32 = count.parse().unwrap_or(0); println!("{}", count); ``` В примере создаются две переменные с типами `&str` и `i32`. Тип `&str` является срезом, указывающим на валидную последовательность UTF-8 символов, в данном случае на строковый литерал. Метод `parse()` преобразует строку в алгебраический тип `Result<>`, содержащий число в случае успешного преобразования либо ошибку. Метод `unwrap_or()` извлекает целочисленное значение из `Result<>` либо возвращает заданное значение в случае ошибки. О типах, включая алгебраические, будет рассказано в следующих главах. ## Константы Константы — это именованные значения, которые вычисляются на этапе компиляции. Основное применение констант — использование вместо [магических чисел](https://ru.wikipedia.org/wiki/%D0%9C%D0%B0%D0%B3%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5_%D1%87%D0%B8%D1%81%D0%BB%D0%BE_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)) для улучшения читабельности кода программы. Синтаксис определения константы: ``` const <name>: <type> = <value>; ``` Имена констант [принято](https://rust-lang.github.io/api-guidelines/naming.html) писать в `SCREAMING_SNAKE_CASE`: ```rust const SECONDS_IN_DAY: u32 = 24 * 60 * 60; ``` Константы похожи на неизменяемые переменные, но имеют ряд существенных отличий: - Тип константы всегда указывается явно. - Значение константы задается при объявлении. А значение переменной может быть задано в любой момент до первого использования. - Константе можно присвоить выражение, если оно вычисляется на этапе компиляции. - Значение константы не изменяется ни при каких условиях. Значение неизменяемой переменной может быть перемещено в другую. - Константа может быть объявлена в любой области видимости, включая глобальную. - Константа доступна в течение всего времени выполнения программы в пределах области, в которой она объявлена. - Затенение констант не допускается, но возможно определение одноименной константы в другой области видимости. Пример: ```rust {.example_for_playground .example_for_playground_004} // допускается наличие неиспользуемого кода #[allow(dead_code)] const LANG_NAME: [char; 6] = ['P', 'y', 't', 'h', 'o', 'n']; // ошибка: нельзя переопределить константу // в той же области видимости const LANG_NAME: [char; 3] = ['C', '+', '+']; // ошибка: значение конcтанты не определено const NAME_LEN_BAD: usize; fn main() { // ошибка: невозможно задать значение // контанты вне объявления NAME_LEN_BAD = LANG_NAME.len(); // длину массива LANG_NAME можно // вычислить на этапе компиляции const NAME_LEN: usize = LANG_NAME.len(); println!("Name — {:?}, length — {}", LANG_NAME, NAME_LEN); const LANG_NAME: [char; 4] = ['R', 'u', 's', 't']; } ``` Если закомментировать ошибочные строки, то на экран будет выведено: ``` Name — ['R', 'u', 's', 't'], length — 4 ``` ## Заключение - Для объявления переменных используется ключевое слово `let`. - Без ключевого слова `mut` переменная является неизменяемой. - Тип переменной можно опустить, если он понятен из контекста. - Использование неинициализированной переменной недопустимо и приведет к ошибке компиляции. - Имена неиспользуемых переменных следует начинать со знака подчеркивания `_`, чтобы избежать предупреждения от компилятора. - Область видимости переменной ограничена блоком `{...}`, в котором она определена. - Определение нескольких переменных с одинаковыми именами в одной области видимости называется затенением. - Для определения констант используется ключевое слово `const`.
Отправка...
Наша группа в telegram. Здесь можно задавать вопросы и общаться.
Задонатить. Если вам нравится курс, вы можете поддержать развитие площадки!