Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Макросы

Функциональность и синтаксис Rust могут быть расширены с помощью пользовательских определений, называемых макросами. Им даются имена, и они вызываются через единообразный синтаксис: some_extension!(...).

Существует два способа определения новых макросов:

  • Макросы по примеру определяют новый синтаксис на более высоком, декларативном уровне.
  • Процедурные макросы определяют функциональноподобные макросы, пользовательские наследования (derives) и пользовательские атрибуты с помощью функций, работающих с входными токенами.

Вызов макроса

Syntax
MacroInvocation
    SimplePath ! DelimTokenTree

DelimTokenTree
      ( TokenTree* )
    | [ TokenTree* ]
    | { TokenTree* }

TokenTree
    Tokenкроме разделителей | DelimTokenTree

MacroInvocationSemi
      SimplePath ! ( TokenTree* ) ;
    | SimplePath ! [ TokenTree* ] ;
    | SimplePath ! { TokenTree* }

Вызов макроса раскрывает макрос во время компиляции и заменяет вызов результатом работы макроса. Макросы могут быть вызваны в следующих ситуациях:

При использовании в качестве элемента или инструкции используется форма MacroInvocationSemi, где точка с запятой требуется в конце, если не используются фигурные скобки. Квалификаторы видимости никогда не разрешаются перед вызовом макроса или определением macro_rules.

#![allow(unused)]
fn main() {
// Используется как выражение.
let x = vec![1,2,3];

// Используется как инструкция.
println!("Hello!");

// Используется в шаблоне.
macro_rules! pat {
    ($i:ident) => (Some($i))
}

if let pat!(x) = Some(1) {
    assert_eq!(x, 1);
}

// Используется в типе.
macro_rules! Tuple {
    { $A:ty, $B:ty } => { ($A, $B) };
}

type N2 = Tuple!(i32, i32);

// Используется как элемент.
use std::cell::RefCell;
thread_local!(static FOO: RefCell<u32> = RefCell::new(1));

// Используется как ассоциированный элемент.
macro_rules! const_maker {
    ($t:ty, $v:tt) => { const CONST: $t = $v; };
}
trait T {
    const_maker!{i32, 7}
}

// Вызовы макросов внутри макросов.
macro_rules! example {
    () => { println!("Макрос внутри макроса!") };
}
// Сначала раскрывается внешний макрос `example`, затем внутренний макрос `println`.
example!();
}