Перейти к содержимому

Синтаксис Rust

Теперь, когда ты умеешь запускать Rust, давай притормозим и посмотрим, что на самом деле значит каждая часть программы. Возьмём самый маленький пример и разберём его по кусочкам.

fn main() {
println!("Hello, World!");
}

Вывод:

Hello, World!
▶ Попробуй сам
fn main() {
// здесь выполняется твой код
}

Любая программа на Rust начинается с функции main. Когда ты запускаешь программу, Rust ищет main и выполняет код внутри неё.

  • fn — ключевое слово для объявления функции (именованного блока кода).
  • main — имя функции. Именно это имя особенное: это точка входа.
  • В () перечисляются входные данные функции (здесь пусто — main ничего не принимает).
  • Фигурные скобки { } обрамляют тело — код, который относится к функции.

Инструкции заканчиваются точкой с запятой

Заголовок раздела «Инструкции заканчиваются точкой с запятой»

Внутри тела каждая команда обычно является инструкцией (statement), а инструкции заканчиваются точкой с запятой ;:

fn main() {
let x = 5;
let y = 10;
println!("{}", x + y);
}

Вывод:

15
▶ Попробуй сам

Забыть точку с запятой там, где она нужна, — одна из самых частых ошибок новичков. Компилятор укажет прямо на это место.

Выражения: код, который возвращает значение

Заголовок раздела «Выражения: код, который возвращает значение»

Код на Rust состоит из двух видов частей, и в Rust разница между ними важнее, чем в большинстве языков:

  • Инструкция (statement) что-то делает, но не возвращает значения. let x = 5; — это инструкция.
  • Выражение (expression) даёт значение. 5, x + 1 и x * 2 — всё это выражения.

А вот что многих удивляет: блок кода в фигурных скобках { } — тоже выражение. Его значение — это последняя строка, записанная без точки с запятой:

fn main() {
let x = 5;
let y = {
let doubled = x * 2; // инструкция внутри блока
doubled + 1 // без точки с запятой: это значение блока
};
println!("y равно {y}");
}

Вывод:

y равно 11
▶ Попробуй сам

Блок выполняет свои инструкции, а затем возвращает doubled + 1, то есть 11, и это значение попадает в y. Обрати внимание на точку с запятой после закрывающей }: вся строка let y = ...; по-прежнему инструкция.

Если поставить точку с запятой после doubled + 1, эта строка перестанет быть значением блока. Тогда блок вернёт «ничего» (в Rust это записывается как ()), а println! не умеет такое печатать, и код не скомпилируется. Правило «без точки с запятой в последней строке» — это ровно то, как функции возвращают значения. Ты встретишь его снова в уроке Функции и в разделе про if как выражение.

Присмотрись к println! — восклицательный знак здесь не опечатка. ! значит, что это макрос, а не обычная функция.

Пока не нужно до конца разбираться в макросах. Просто запомни: если видишь !, это макрос. Сейчас ты будешь пользоваться только одним — println!, чтобы печатать текст.

fn main() {
println!("Это вызов макроса");
}

Внутри println! фигурные скобки {} — это заполнители (placeholders): в них подставляются значения, которые ты передаёшь после текста:

fn main() {
let name = "Феррис";
let age = 10;
println!("{} уже {} лет", name, age);
}

Вывод:

Феррис уже 10 лет
▶ Попробуй сам

Имя переменной можно написать прямо внутри скобок — часто так получается чище:

println!("{name} уже {age} лет");

В отличие от Python, Rust не важны отступы: чтобы понять, где начинается и заканчивается блок, он смотрит на фигурные скобки { }. Отступы нужны только людям, чтобы код было легче читать.

При этом у сообщества есть стандартный стиль, а вместе с Rust поставляется инструмент, который автоматически приводит к нему код:

Terminal window
cargo fmt

cargo fmt переформатирует твой код в официальном стиле. Возьми в привычку им пользоваться.

В коде можно оставлять заметки, которые Rust пропускает. Это комментарии, и они начинаются с //:

fn main() {
// Это комментарий — Rust его пропускает
println!("Привет!"); // комментарий можно поставить и в конце строки
}

Подробнее о комментариях — на следующей странице.

Создай две переменные, a = 7 и b = 3, и выведи 7 + 3 = 10. Пусть сложение выполнит Rust. Подсказка: в println! может быть несколько заполнителей {}, они заполняются по порядку значениями после текста.

Показать решение
fn main() {
let a = 7;
let b = 3;
println!("{} + {} = {}", a, b, a + b);
}

Вывод:

7 + 3 = 10
▶ Попробуй сам

Магазин продаёт 3 товара по цене 4 за штуку, плюс 2 за доставку. Вычисли total с помощью блока { }: внутри него создай subtotal, а затем верни subtotal + 2. Выведи Итого: 14. Подсказка: в последней строке блока не должно быть точки с запятой.

Показать решение
fn main() {
let price = 4;
let quantity = 3;
let total = {
let subtotal = price * quantity;
subtotal + 2 // доставка
};
println!("Итого: {total}");
}

Вывод:

Итого: 14
▶ Попробуй сам
  • Любая программа начинается в функции main.
  • Код живёт внутри фигурных скобок { }; большинство инструкций заканчиваются ;.
  • Инструкции что-то делают; выражения дают значение. Последняя строка блока без ; — его значение.
  • ! (как в println!) значит, что это макрос.
  • {} внутри println! — заполнители, в которые подставляются переданные значения.
  • Отступы нужны для читаемости — запускай cargo fmt, чтобы форматировать код автоматически.

Проверь себя

1. Чем особенна функция main в программе на Rust?

2. Что значит ! после println?

3. Чему равно y после let y = { let a = 2; a + 1 };?

Результат: 0 / 3