Перейти к содержанию
Educora
Начальный16 мин2 / 10

Переменные, изменяемость и типы

Создавай переменные через `let` и `mut`, пользуйся затенением и изучи скалярные типы Rust (целые и дробные числа, `bool`, `char`) и составные типы (кортежи и массивы).

Проверь себя
В этом уроке ты узнаешь
  • Создавать неизменяемые и изменяемые (mut) переменные и объявлять константы через const
  • Объяснять, чем затенение отличается от mut
  • Выбирать подходящий целый, дробный, логический и символьный тип и безопасно обрабатывать переполнение
  • Работать с кортежами и массивами

Баланс на банковской карте меняется каждый день, а дата рождения — никогда. Во многих языках оба значения хранятся одинаково, и дату рождения можно случайно «изменить». Rust заставляет решить заранее: переменная по умолчанию неизменяема, и если она должна меняться, это нужно указать явно.

let, mut и const

Переменная создаётся ключевым словом let. Тип обычно писать не нужно: компилятор выводит его из значения. Если значение потом будет меняться, поставь перед именем mut (от английского mutable — изменяемый). Имена переменных в Rust пишут в стиле snake_case: total_score, user_name.

Rust
fn main() {
    let city = "Baku";
    let mut score = 10;
    println!("{city}: {score}");

    score += 5;
    println!("{city}: {score}");
}
Ожидаемый результат
Baku: 10
Baku: 15
Ошибка E0384
fn main() {
    let score = 10;
    println!("{score}");
    score = 15;
    println!("{score}");
}
Правильно с `mut`
fn main() {
    let mut score = 10;
    println!("{score}");
    score = 15;
    println!("{score}");
}
Неизменяемой переменной нельзя присвоить значение второй раз. Программа справа выводит 10 и 15.
Text
error[E0384]: cannot assign twice to immutable variable `score`
 --> src/main.rs:4:5
  |
2 |     let score = 10;
  |         ----- first assignment to `score`
3 |     println!("{score}");
4 |     score = 15;
  |     ^^^^^^^^^^ cannot assign twice to immutable variable
  |
help: consider making this binding mutable
  |
2 |     let mut score = 10;
  |         +++
Сообщения об ошибках в Rust очень подробные: они указывают на проблемную строку и даже предлагают исправление (+++ отмечает текст, который нужно добавить).

Константы объявляются через const. Их тип нужно указывать всегда, имена пишут ЗАГЛАВНЫМИ_БУКВАМИ, а значение должно быть известно при компиляции. Константу можно объявить и вне main, в начале файла.

Rust
const MAX_PLAYERS: u32 = 4;
const SECONDS_PER_HOUR: u32 = 60 * 60;

fn main() {
    println!("Players: {}", MAX_PLAYERS);
    println!("Seconds in 2 hours: {}", 2 * SECONDS_PER_HOUR);
}
Ожидаемый результат
Players: 4
Seconds in 2 hours: 7200

Затенение

Если снова написать let с тем же именем, создаётся новая переменная, которая закрывает старую, — это называется затенением (shadowing). При затенении можно даже сменить тип значения. Затенение во внутреннем блоке ({ }) исчезает, когда блок заканчивается.

Rust
fn main() {
    let spaces = "   ";
    let spaces = spaces.len();
    println!("spaces = {spaces}");

    let x = 5;
    let x = x + 1;
    {
        let x = x * 2;
        println!("inner x = {x}");
    }
    println!("outer x = {x}");
}
Ожидаемый результат
spaces = 3
inner x = 12
outer x = 6
spaces сначала была текстом, а потом стала числом. С mut так нельзя: mut позволяет менять значение переменной, но не её тип.

Скалярные типы

Скалярный тип хранит одно значение. В Rust их четыре вида: целые числа, числа с плавающей точкой, логический bool (true/false) и символ char. Имя целого типа показывает знак и размер: i — знаковый (может быть отрицательным), u — беззнаковый, а число — количество битов. Если тип не указан, целое число будет i32, а дробное — f64.

ТипДиапазон или содержимоеГде пригодится
u80 … 255байты, компоненты цвета, возраст
i32−2 147 483 648 … 2 147 483 647обычные целые числа (тип по умолчанию)
i64, u64примерно ±9,2 · 10¹⁸большие счётчики, отметки времени
usize64 бита в 64-битной системеиндексы и длины
f64примерно 15–16 точных цифрдробные числа (тип по умолчанию)
booltrue, falseусловия
charлюбой символ Unicode, 4 байтаотдельные буквы и знаки
Rust
fn main() {
    let age: u8 = 14;
    let temperature: i32 = -3;
    let price: f64 = 2.5;
    let whole: f64 = 10.0;
    let is_open = true;
    let currency = '₼';

    println!("{age} {temperature} {price} {whole} {is_open} {currency}");
    println!("{:?} {:.2}", whole, price);
    println!("{} {} {}", 7 / 2, 7 % 2, 7.0 / 2.0);
    println!("{} {}", 3.9_f64 as i32, u8::MAX);
}
Ожидаемый результат
14 -3 2.5 10 true ₼
10.0 2.50
3 1 3.5
3 255
Обрати внимание: {} выводит 10.0 как 10, а {:?} — как 10.0. {:.2} оставляет два знака после точки. Деление целых отбрасывает дробную часть, а as преобразует тип.
Rust
fn main() {
    let level: u8 = 250;
    println!("{:?}", level.checked_add(10));
    println!("{:?}", level.checked_add(5));
    println!("{}", level.saturating_add(10));
    println!("{}", level.wrapping_add(10));
}
Ожидаемый результат
None
Some(255)
255
4
Some и None означают «значение есть» и «значения нет» — с этим типом Option ты познакомишься в 5-м уроке. 250 + 10 = 260, а 260 − 256 = 4.

Составные типы: кортежи и массивы

Кортеж (tuple) хранит вместе несколько значений разных типов: ("Murad", 15, 4.5). К его элементам обращаются через точку и индекс (student.0) или раскладывают кортеж на отдельные переменные: let (a, b, c) = .... Массив — последовательность элементов одного типа фиксированного размера: его тип пишется как [i32; 5], а к элементам обращаются так: days[0].

Rust
fn main() {
    let student: (&str, u8, f64) = ("Murad", 15, 4.5);
    let (name, age, grade) = student;
    println!("{name} is {age}, average grade {grade}");
    println!("First field: {}", student.0);

    let days = ["Mon", "Tue", "Wed", "Thu", "Fri"];
    let zeros = [0; 3];
    println!("{} days, first: {}", days.len(), days[0]);
    println!("{:?}", zeros);
    println!("{:?}", student);
}
Ожидаемый результат
Murad is 15, average grade 4.5
First field: Murad
5 days, first: Mon
[0, 0, 0]
("Murad", 15, 4.5)
[0; 3] означает «три нуля». Массивы и кортежи печатают через {:?}, а он показывает текст в кавычках.

Главное

  • В Rust переменные по умолчанию неизменяемы; чтобы менять их, пиши let mut.
  • У константы const тип указывается обязательно, а значение должно быть известно при компиляции.
  • Затенение создаёт новую переменную с тем же именем и позволяет сменить тип.
  • Типы по умолчанию: i32 для целых и f64 для дробных; char — любой символ Unicode.
  • Обрабатывай переполнение явно через checked_add, saturating_add или wrapping_add.
  • Кортеж хранит значения разных типов, а массив — фиксированное число элементов одного типа.

Проверь себя

Вопросов: 10. Каждый правильный ответ приносит XP.

1 / 10
Что произойдёт с кодом let x = 5; x = 6;?