rust-macros

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Rust Macros Skill

Rust 宏 Skill

Master Rust's macro system: declarative macros (macro_rules!) and procedural macros.
掌握 Rust 的宏系统:声明式宏(macro_rules!)和过程式宏。

Quick Start

快速开始

Declarative Macros

声明式宏

rust
macro_rules! vec_of_strings {
    ($($x:expr),* $(,)?) => {
        vec![$($x.to_string()),*]
    };
}

let v = vec_of_strings!["a", "b", "c"];
rust
macro_rules! vec_of_strings {
    ($($x:expr),* $(,)?) => {
        vec![$($x.to_string()),*]
    };
}

let v = vec_of_strings!["a", "b", "c"];

Fragment Specifiers

片段说明符

SpecifierMatches
ident
Identifier
expr
Expression
ty
Type
pat
Pattern
tt
Token tree
literal
Literal
说明符匹配内容
ident
标识符
expr
表达式
ty
类型
pat
模式
tt
Token 树
literal
字面量

Repetition

重复

rust
macro_rules! hashmap {
    ($($key:expr => $value:expr),* $(,)?) => {{
        let mut map = std::collections::HashMap::new();
        $(map.insert($key, $value);)*
        map
    }};
}

let m = hashmap! { "one" => 1, "two" => 2 };
rust
macro_rules! hashmap {
    ($($key:expr => $value:expr),* $(,)?) => {{
        let mut map = std::collections::HashMap::new();
        $(map.insert($key, $value);)*
        map
    }};
}

let m = hashmap! { "one" => 1, "two" => 2 };

Procedural Macros

过程式宏

toml
[lib]
proc-macro = true

[dependencies]
syn = { version = "2", features = ["full"] }
quote = "1"
toml
[lib]
proc-macro = true

[dependencies]
syn = { version = "2", features = ["full"] }
quote = "1"

Derive Macro

派生宏

rust
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};

#[proc_macro_derive(HelloMacro)]
pub fn hello_derive(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    let name = input.ident;

    quote! {
        impl HelloMacro for #name {
            fn hello() {
                println!("Hello from {}!", stringify!(#name));
            }
        }
    }.into()
}
rust
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};

#[proc_macro_derive(HelloMacro)]
pub fn hello_derive(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    let name = input.ident;

    quote! {
        impl HelloMacro for #name {
            fn hello() {
                println!("Hello from {}!", stringify!(#name));
            }
        }
    }.into()
}

Debugging

调试

bash
cargo expand              # Expand all macros
cargo expand main         # Expand specific
bash
cargo expand              # Expand all macros
cargo expand main         # Expand specific

Troubleshooting

故障排查

ProblemSolution
Hygiene issuesUse
$crate::
Order mattersDefine before use
问题解决方案
卫生性问题使用
$crate::
顺序很重要先定义后使用

Resources

资源