- Создавать неизменяемые и изменяемые (
mut) переменные и объявлять константы черезconst - Объяснять, чем затенение отличается от
mut - Выбирать подходящий целый, дробный, логический и символьный тип и безопасно обрабатывать переполнение
- Работать с кортежами и массивами
Баланс на банковской карте меняется каждый день, а дата рождения — никогда. Во многих языках оба значения хранятся одинаково, и дату рождения можно случайно «изменить». Rust заставляет решить заранее: переменная по умолчанию неизменяема, и если она должна меняться, это нужно указать явно.
let, mut и const
Переменная создаётся ключевым словом let. Тип обычно писать не нужно: компилятор выводит его из значения. Если значение потом будет меняться, поставь перед именем mut (от английского mutable — изменяемый). Имена переменных в Rust пишут в стиле snake_case: total_score, user_name.
fn main() {
let city = "Baku";
let mut score = 10;
println!("{city}: {score}");
score += 5;
println!("{city}: {score}");
}Baku: 10 Baku: 15
fn main() {
let score = 10;
println!("{score}");
score = 15;
println!("{score}");
}fn main() {
let mut score = 10;
println!("{score}");
score = 15;
println!("{score}");
}10 и 15.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;
| ++++++ отмечает текст, который нужно добавить).Константы объявляются через const. Их тип нужно указывать всегда, имена пишут ЗАГЛАВНЫМИ_БУКВАМИ, а значение должно быть известно при компиляции. Константу можно объявить и вне main, в начале файла.
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). При затенении можно даже сменить тип значения. Затенение во внутреннем блоке ({ }) исчезает, когда блок заканчивается.
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.
| Тип | Диапазон или содержимое | Где пригодится |
|---|---|---|
u8 | 0 … 255 | байты, компоненты цвета, возраст |
i32 | −2 147 483 648 … 2 147 483 647 | обычные целые числа (тип по умолчанию) |
i64, u64 | примерно ±9,2 · 10¹⁸ | большие счётчики, отметки времени |
usize | 64 бита в 64-битной системе | индексы и длины |
f64 | примерно 15–16 точных цифр | дробные числа (тип по умолчанию) |
bool | true, false | условия |
char | любой символ Unicode, 4 байта | отдельные буквы и знаки |
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 преобразует тип.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].
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.
let x = 5; x = 6;?