Rust宏的一个例子:DSL

转载自https://rustwiki.org/zh-CN/rust-by-example/macros/variadics.html

DSL 是 Rust 的宏中集成的微型 “语言”。这种语言是完全合法的,因为宏系统会把它转换 成普通的 Rust 语法树(不是简单的替换,避免带来优先级问题),它只不过看起来像是另一种语言而已。这就允许你为一些特定功能 创造一套简洁直观的语法(当然是有限制的)。

比如说我想要定义一套小的计算器 API,可以传给它表达式,它会把结果打印到控制台上。

macro_rules! calculate {
    (eval $e:expr) => {
        let val: usize = $e;    // 强制类型为整形
        println!("{} = {}", stringify!{$e}, val);
    };
}

fn main(){
    calculate!{eval 1+2};  // 看到了吧,`eval` 可并不是 Rust 的关键字!
    calculate!{eval (1+2)*(8/4)};
}

输出:

1 + 2 = 3
(1 + 2) * (8 / 4) = 6

这个例子非常简单,但是已经有很多利用宏开发的复杂接口了,比如 lazy_static 和 clap

可变参数接口

可变参数接口可以接受任意数目的参数。比如说 println 就可以,其参数的数目是由 格式化字符串指定的。

我们可以把之前的 calculater! 宏改写成可变参数接口:

macro_rules! calculate {
    // 单个 'eval' 模式
    (eval $e:expr) => {
        let val: usize = $e;    // 强制类型为整形
        println!("{} = {}", stringify!{$e}, val);
    };

    // 递归的拆解多重 'eval'
    (eval $e:expr, $(eval $es:expr),+) => {
        calculate! {eval $e}
        calculate! {$(eval $es),+}
    };
}

fn main(){
    calculate!{
        eval 1+1,
        eval (1+2)*3/4,
        eval 2*3
    };
}

输出:

1 + 1 = 2
(1 + 2) * 3 / 4 = 2
2 * 3 = 6
posted @ 2021-09-17 16:59  Rogn  阅读(517)  评论(0编辑  收藏  举报