0Pricing
Learn Rust Coding · Урок

Декларативные макросы (`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 — локальная установка не требуется.

Все уроки этого курса

  1. Декларативные макросы (`macro_rules!`)
  2. Процедурные макросы: Derive, Function
  3. Взаимодействие с небезопасным Rust
← Назад к Learn Rust Coding