0Pricing
Learn Rust Coding · 课时

声明式宏(`macro_rules!`)

学习编写声明式宏,以抽象重复的代码模式,并在编译时生成代码。

声明式宏(`macro_rules!`) 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 1 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 3 节课。

什么是 Rust 宏?

宏是一种编写能够生成代码的代码的方式!它们类似于函数,但操作的是语法树(即代码的结构),而不是值。

  • 它们有助于抽象重复代码。
  • 它们支持在 Rust 中实现领域专用语言(DSL)。
  • 它们在编译时运行,在编译开始前展开为普通的 Rust 代码。

声明式宏语法

Rust 的声明式宏使用macro_rules!关键字。它们定义一组规则,用于匹配特定的 Rust 代码模式。

您可以把它理解为针对代码片段的模式匹配。当编译器看到宏调用时,它会尝试将输入与您定义的某条规则匹配。

您的第一个 `macro_rules!`

让我们创建一个非常简单的宏,用于打印问候语。请注意macro_rules!关键字和() => {}语法,它定义了一个不带输入模式的规则。

请尝试运行这个示例:

macro_rules! greet {
    () => {
        println!("Hello from a macro!");
    };
}

fn main() {
    greet!(); // Call our macro!
}

使用设计符捕获输入

宏可以使用“设计符”接收输入。这些设计符会告诉宏应当捕获哪种 Rust 语法。

  • $expr:一个表达式(例如1 + 2、"hello")
  • $ident:一个标识符(例如变量名、函数名)
  • $ty:一个类型(例如i32、String)
  • $block:一个代码块(例如{ ... })
  • ……以及更多!

接收参数的宏

下面是一个接收表达式($e:expr)并打印其值的宏。这里的:expr就是设计符。

捕获的$e随后就可以在宏体中使用。stringify!宏会将表达式转换为其字符串表示形式。

macro_rules! debug_print {
    ($e:expr) => {
        println!("Debug: {} = {:?}", stringify!($e), $e);
    };
}

fn main() {
    let x = 10;
    debug_print!(x + 5);
    debug_print!("Rust macros are fun");
}

处理多个输入

如果您希望宏接受多个相同类型的参数,可以使用重复运算符:$()*。

  • $():其中的内容是要重复的模式。
  • *:重复零次或多次。
  • +:重复一次或多次。
  • 您还可以指定分隔符,例如使用 $(...),* 表示以逗号分隔的项目。

带重复参数的宏

让我们创建一个接受多个表达式(以逗号分隔)的宏,并分别打印每个表达式。这对于创建类似列表的结构非常有用。

macro_rules! print_all {
    ( $( $x:expr ),* ) => {
        $( // This $(...)* repeats the `println!` call
            println!("Item: {:?}", $x);
        )*
    };
}

fn main() {
    print_all!(1, "hello", true, 3.14);
    print_all!("Just one item");
}

理解宏卫生性

Rust 的宏具有“卫生性”。这意味着,在宏内部定义的变量不会意外地与宏外部的变量发生冲突,即使它们的名称相同。

编译器会在展开过程中在内部重命名相关内容,以避免非预期的副作用,从而让宏更安全、更易于预测。

如何调试宏

有时宏的展开结果可能与您的预期不同。Rust 提供了查看展开后代码的方法:

  • 运行 cargo expand(需要安装 cargo-expand 工具)
  • 直接对源文件使用 rustc --pretty expanded。

这会显示宏生成的原始 Rust 代码,对于调试和理解复杂的宏行为非常有帮助!

宏模式匹配测验

请考虑以下宏定义:

macro_rules! make_tuple {
    ( $x:expr, $y:expr ) => {
        ($x, $y)
    };
}

以下哪一行可以成功编译并使用 make_tuple! 宏?

回顾:声明式宏

在本课中,您学习了使用 macro_rules! 的声明式宏:

  • 它们在编译时生成代码,将重复的模式抽象出来。
  • 它们使用模式匹配,根据语法捕获输入。
  • 诸如 $expr、$ident 这样的指示符用于指定预期的语法类型。
  • 诸如 $()* 这样的重复运算符可以处理带有灵活分隔符的多个参数。
  • 宏具有卫生性,可以防止名称意外冲突。

宏是 Rust 中减少样板代码以及创建灵活、易用 API 的强大工具!

常见问题解答

「声明式宏(`macro_rules!`)」课时是免费的吗?

是的 — 「声明式宏(`macro_rules!`)」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 3 节课。

「声明式宏(`macro_rules!`)」这节课中我会学到什么?

学习编写声明式宏,以抽象重复的代码模式,并在编译时生成代码。 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Learn Rust Coding 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 3 节。

「声明式宏(`macro_rules!`)」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Learn Rust Coding 课中编写并运行代码吗?

能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 声明式宏(`macro_rules!`)
  2. 过程宏:派生宏与函数宏
  3. 与不安全 Rust 交互
← 返回 Learn Rust Coding