Rustlings Part22: — Macros in Rust

201 阅读2分钟

LearningOS/rust-based-os-comp2023

Rustlings Part22: — Macros in Rust

You can do it

Macros

Rust's macro system is very powerful, but also kind of difficult to wrap your head around. We're not going to teach you how to write your own fully-featured macros. Instead, we'll show you how to use and create them.

If you'd like to learn more about writing your own macros, the macrokata project has a similar style of exercises to Rustlings, but is all about learning to write Macros.

Further information

course.rs/advance/mac…

从根本上来说,宏是通过一种代码来生成另一种代码,如果大家熟悉元编程,就会发现两者的共同点。

所有的这些都是在编译期发生,并没有运行期的性能损耗。

#[macro_export]
macro_rules! vec {
    ( $( $x:expr ),* ) => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
            )*
            temp_vec
        }
    };
}

由于 vec 宏只有一个模式,因此它只能匹配一种源代码,其它类型的都将导致报错,而更复杂的宏往往会拥有更多的分支。

虽然宏和 match 都称之为模式,但是前者跟后者的模式规则是不同的。如果大家想要更深入的了解宏的模式,可以查看这里。

模式解析 而现在,我们先来简单讲解下 ( (( x:expr ),* ) 的含义。

首先,我们使用圆括号 () 将整个宏模式包裹其中。紧随其后的是 (),跟括号中模式相匹配的值(传入的Rust源代码)会被捕获,然后用于代码替换。在这里,模式(),跟括号中模式相匹配的值(传入的 Rust 源代码)会被捕获,然后用于代码替换。在这里,模式 x:expr 会匹配任何 Rust 表达式并给予该模式一个名称:$x。

()之后的逗号说明在() 之后的逗号说明在 () 所匹配的代码的后面会有一个可选的逗号分隔符,紧随逗号之后的 * 说明 * 之前的模式会被匹配零次或任意多次(类似正则表达式)。

当我们使用 vec![1, 2, 3] 来调用该宏时,$x 模式将被匹配三次,分别是 1、2、3。为了帮助大家巩固,我们再来一起过一下:

()中包含的是模式() 中包含的是模式 x:expr,该模式中的 expr 表示会匹配任何 Rust 表达式,并给予该模式一个名称 x因此x 因此 x 模式可以跟整数 1 进行匹配,也可以跟字符串 "hello" 进行匹配: vec!["hello", "world"] $() 之后的逗号,意味着1 和 2 之间可以使用逗号进行分割,也意味着 3 既可以没有逗号,也可以有逗号:vec![1, 2, 3,]

  • 说明之前的模式可以出现零次也可以任意次,这里出现了三次

// macros4.rs
//
// Execute `rustlings hint macros4` or use the `hint` watch subcommand for a
// hint.


#[rustfmt::skip]
macro_rules! my_macro {
    () => {
        println!("Check out my macro!");
    };
    ($val:expr) => {
        println!("Look at this other macro: {}", $val);
    }
}

fn main() {
    my_macro!();
    my_macro!(7777);
}

本文由mdnice多平台发布