标签: rust

  • Rust中的macro_rules!宏用法

        rust lang的宏可能有些人学习比较困难,我自己也是花了很多时间才看懂,这里把认为最难理解的公布出来,希望让更多的人能够减少学习难度,更好的学习rust

        首先在说明rust lang宏的用法的时候,记住一个要点:rust lang的宏思想基于匹配(match),实际上这门语言的基本思想都是基于匹配.

    rust lang的宏规则写法是:

    macro_rules! macro_name {
        () =>{{
            ...
        }}
    }

    上面的基本规则怎么理解呢,我们知道rust调用宏的语法是 macro_name!() ,那么这里”()”代表上面宏规则的”()”,”{}”代表宏块.
    先看一个简单的例子:

    macro_rules! MyMacro{
        ($x:expr)=>{{    
            $x   
        }}
    }
    

    上面怎么理解呢:”$”读作匹配 , “$x:expr”可读作匹配x,并且x是一个表达式,”$x”后的”:”表示”$x”的属性,rust的宏匹配有很多属性,这里可以看官方手册,”{$x}”表示返回匹配的x的值(注意这里的$x没有分号),
    然后我们可以这样使用:

    let z=MyMacro!(10000); //z的值将会是10000

    看这个官方的例子:

    let x: Vec<u32> = vec![1, 2, 3];

    宏展开之后应该是这样子的:

    let x: Vec = {
        let mut temp_vec = Vec::new();
        temp_vec.push(1);
        temp_vec.push(2);
        temp_vec.push(3);
        temp_vec
    };
    

    那么实现的代码如下:

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

    上面的代码怎么理解呢:我们知道正则表达式的”*”表示匹配0个或者多个,”+”表示匹配一个或者多个,”?”表示匹配0个或者一个,上面的
    “*”就代表匹配0个或者多个的”$x:expr”,$(temp_vec.push($x))*表示匹配0个或者多个push方法,然后这个宏返回Vec对象。

    我们再来看另外一个不同的例子:

    macro_rules! MyMacro{
        (x=>$v:expr) => ($v)
    }
    

    这个例子可能有些人会疑惑,右边不是”{ }”吗,为何变成”( )”了,这里说明一下,rust lang宏块可以是”[ ]”,”{ }”和”()”,具体看官方手册,
    我这里不详细说明,这个文章重点在于列出难理解的部分。其实右边的”( )”换成
    “{ }”也可以.
    上面的宏使用例子如下

     let z=MyMacro!(x=>1000);
    /*注意这里不能写成 y=>1000,因为之前讲过,rust的宏思想是基于匹配*/
    /* 上面的宏如果是这样 */
    macro_rules! MyMacro2{
        (1,x=>$v:expr) => ($v)
    }
    // 调用时如下
    let zz=MyMacro2!(1,x=>1000);
    

    读到这里,你或许知道rust macro的用法了吧😊,更多详细说明请观看官方的教程,
    链接如下:
    https://doc.rust-lang.org/1.7.0/book/macros.html