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
个性签名:时间会解决一切