Декларативные макросы (`macro_rules!`)
Научитесь писать декларативные макросы для абстрагирования повторяющихся шаблонов кода и генерации кода во время компиляции.
«Декларативные макросы (`macro_rules!`)» — бесплатный урок Learn Rust Coding на CoddyKit. Это урок 1 из 3. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Learn Rust Coding, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Learn Rust Coding содержит 3 уроков всего.
Что такое макросы Rust
Макросы позволяют писать код, который пишет код! Они похожи на функции, но работают с синтаксическими деревьями (структурой Вашего кода), а не со значениями.
- Они помогают обобщать повторяющийся код.
- Они позволяют создавать предметно-ориентированные языки (DSL) внутри Rust.
- Они выполняются во время компиляции, разворачиваясь в обычный код Rust до начала компиляции.
Синтаксис декларативных макросов
В декларативных макросах Rust используется ключевое слово macro_rules!. С его помощью задаётся набор правил, соответствующих определённым шаблонам кода Rust.
Представляйте это как сопоставление с шаблоном для фрагментов кода. Когда компилятор встречает вызов макроса, он пытается сопоставить входные данные с одним из определённых Вами правил.
Ваш первый `macro_rules!`
Создадим очень простой макрос, который выводит приветствие. Обратите внимание на ключевое слово macro_rules! и синтаксис () => {}, задающий правило без входного шаблона.
Попробуйте запустить этот пример:
macro_rules! greet {
() => {
println!("Hello from a macro!");
};
}
fn main() {
greet!(); // Call our macro!
}Захват входных данных с помощью спецификаторов
Макросы могут принимать входные данные с помощью «спецификаторов». Они сообщают макросу, какой вид синтаксиса Rust следует ожидать и захватывать.
$expr: выражение (например,1 + 2,"hello")$ident: идентификатор (например, имя переменной или функции)$ty: тип (например,i32,String)$block: блок кода (например,{ ... })- ...и многое другое!
Макросы с аргументами
Вот макрос, который принимает выражение ($e:expr) и выводит его значение. :expr — это спецификатор.
Захваченное значение $e становится доступным для использования в теле макроса. Макрос stringify! преобразует выражение в его строковое представление.
macro_rules! debug_print {
($e:expr) => {
println!("Debug: {} = {:?}", stringify!($e), $e);
};
}
fn main() {
let x = 10;
debug_print!(x + 5);
debug_print!("Rust macros are fun");
}Обработка нескольких входных данных
Что делать, если Вы хотите, чтобы макрос принимал несколько аргументов одного типа? Можно использовать операторы повторения: $()*.
$(): содержимое внутри — шаблон для повторения.*: ноль или более повторений.+: одно или более повторений.- Также можно указать разделитель, например
$(...),*для элементов, разделённых запятыми.
Макрос с повторяющимися аргументами
Создадим макрос, который принимает несколько выражений, разделённых запятыми, и выводит каждое из них отдельно. Это удобно для создания структур, похожих на списки.
macro_rules! print_all {
( $( $x:expr ),* ) => {
$( // This $(...)* repeats the `println!` call
println!("Item: {:?}", $x);
)*
};
}
fn main() {
print_all!(1, "hello", true, 3.14);
print_all!("Just one item");
}Понимание гигиены макросов
Макросы Rust являются «гигиеничными». Это означает, что переменные, определённые внутри макроса, не будут случайно конфликтовать с переменными за его пределами, даже если у них одинаковые имена.
Во время раскрытия компилятор внутренне переименовывает элементы, чтобы предотвратить непреднамеренные побочные эффекты. Благодаря этому макросы безопаснее и предсказуемее в использовании.
Отладка макросов
Иногда макросы раскрываются не так, как Вы ожидаете. Rust предоставляет способ просмотреть раскрытый код:
- Запустите
cargo expand(требуется установить инструментcargo-expand) - Используйте
rustc --pretty expandedнепосредственно для исходного файла.
Это покажет необработанный код Rust, который генерирует Ваш макрос, что чрезвычайно полезно для отладки и понимания сложного поведения макросов!
Тест на сопоставление с шаблоном макроса
Рассмотрим следующее определение макроса:
macro_rules! make_tuple {
( $x:expr, $y:expr ) => {
($x, $y)
};
}Какая из следующих строк успешно скомпилируется и использует макрос make_tuple!?
Повторение: декларативные макросы
В этом уроке Вы узнали о декларативных макросах, использующих macro_rules!:
- Они генерируют код во время компиляции, абстрагируя повторяющиеся шаблоны.
- Они используют сопоставление с шаблоном, чтобы извлекать входные данные на основе синтаксиса.
- Обозначатели, такие как
$exprи$ident, указывают, какой вид синтаксиса следует ожидать. - Операторы повторения, такие как
$()*, обрабатывают несколько аргументов с гибкими разделителями. - Макросы являются гигиеничными и предотвращают случайные конфликты имён.
Макросы — мощный инструмент для сокращения шаблонного кода и создания гибких, удобных интерфейсов программирования в Rust!
Часто задаваемые вопросы
Урок «Декларативные макросы (`macro_rules!`)» бесплатный?
Да — полный текст урока «Декларативные макросы (`macro_rules!`)» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Learn Rust Coding, подпишись на CoddyKit PRO. Курс Learn Rust Coding содержит 3 уроков всего.
Чему я научусь в уроке «Декларативные макросы (`macro_rules!`)»?
Научитесь писать декларативные макросы для абстрагирования повторяющихся шаблонов кода и генерации кода во время компиляции. Ты практикуешь Learn Rust Coding с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Learn Rust Coding?
Предыдущий опыт не требуется. Learn Rust Coding на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 3.
Сколько времени занимает урок «Декларативные макросы (`macro_rules!`)»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Learn Rust Coding?
Да. Каждый урок Learn Rust Coding включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Декларативные макросы (`macro_rules!`)
- Процедурные макросы: Derive, Function
- Взаимодействие с небезопасным Rust