Rust 的功能和语法可以通过称为宏的自定义定义进行扩展。它们被赋予名称,并通过一致的语法调用:some_extension!(...)

有两种方法可以定义新的宏

  • 示例宏 以更高级别、声明性的方式定义新语法。
  • 过程宏 使用对输入词法单元进行操作的函数来定义类似函数的宏、自定义派生和自定义属性。

宏调用

语法

MacroInvocation :

   简单路径 ! 分隔词法单元树

DelimTokenTree :

      ( 词法单元树* )

   | [ 词法单元树* ]

   | { 词法单元树* }

词法单元树 :

   词法单元分隔符 之外 | 分隔词法单元树

MacroInvocationSemi :

      简单路径 ! ( 词法单元树* ) ;

   | 简单路径 ! [ 词法单元树* ] ;

   | 简单路径 ! { 词法单元树* }

宏调用在编译时展开宏,并用宏的结果替换调用。宏可以在以下情况下被调用

当用作项或语句时,使用 MacroInvocationSemi 形式,其中在不使用花括号时,末尾需要一个分号。可见性限定符 不允许出现在宏调用或 macro_rules 定义之前。

#![allow(unused)]
fn main() {
// Used as an expression.
let x = vec![1,2,3];

// Used as a statement.
println!("Hello!");

// Used in a pattern.
macro_rules! pat {
    ($i:ident) => (Some($i))
}

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

// Used in a type.
macro_rules! Tuple {
    { $A:ty, $B:ty } => { ($A, $B) };
}

type N2 = Tuple!(i32, i32);

// Used as an item.
use std::cell::RefCell;
thread_local!(static FOO: RefCell<u32> = RefCell::new(1));

// Used as an associated item.
macro_rules! const_maker {
    ($t:ty, $v:tt) => { const CONST: $t = $v; };
}
trait T {
    const_maker!{i32, 7}
}

// Macro calls within macros.
macro_rules! example {
    () => { println!("Macro call in a macro!") };
}
// Outer macro `example` is expanded, then inner macro `println` is expanded.
example!();
}