macros.md
commit 771c5d10cf944bf7d221f5d6cb7abd2a06c400e4

Rust 语言的功能和语法可以通过自定义宏进行扩展。宏可以被命名,可通过一致的语法调用:some_extension!(...)

定义新宏有两种方式:

  • 声明宏以更高级别的声明性方式定义新语法。
  • 过程宏可用于实现自定义派生。

宏调用

Syntax
MacroInvocation :
   SimplePath ! DelimTokenTree

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

TokenTree :
   Tokenexcept delimiters | DelimTokenTree

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

宏调用在编译时执行宏,并用执行结果替换调用。可以在下述情况中调用宏:

当用作项或语句时,MacroInvocationSemi 形式被使用。MacroInvocationSemi 形式中,如果不使用大括号,则在结尾处需要分号。在宏调用或声明宏定义之前,不允许使用可见性限定符


#![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!();
}