Macros
宏
macros.md
commit: 93f9325701a4c8beba06cb439c1fa88b26893844
本章译文最后维护日期:2022-08-21
可以使用称被为宏的自定义句法形式来扩展 Rust 的功能和句法。宏需要被命名,并通过一致的句法去调用:some_extension!(...)
。
定义新宏有两种方式:
- 声明宏(Macros by Example)以更高级别的声明性的方式定义了一套新句法规则。
- 过程宏(Procedural Macros)使用操作输入的token的函数来定义类函数宏、自定义派生和自定义属性。
Macro Invocation
宏调用
句法
MacroInvocation :
SimplePath!
DelimTokenTreeDelimTokenTree :
(
TokenTree*)
|[
TokenTree*]
|{
TokenTree*}
TokenTree :
Token排除 定界符(delimiters) | DelimTokenTreeMacroInvocationSemi :
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!("Macro call in a macro!") }; } // 外部宏 `example` 展开后, 内部宏 `println` 才会展开. example!(); }