Rust声明宏如何区分普通表达式参数与闭包表达式参数
这个需求完全可以在Rust中实现,核心利用macro_rules!从上到下匹配分支的特性,优先匹配闭包的语法特征,再走普通表达式的兜底逻辑即可。
实现原理
macro_rules!的匹配分支会按编写顺序依次尝试匹配,只要我们把闭包的匹配分支放在普通表达式分支前面,就能在捕获通用expr之前,先识别到闭包特有的开头|语法,优先走闭包分支。
示例代码
macro_rules! generate_code { // 匹配无参非移动闭包 (|| $($closure_body:tt)*) => { do_sth(|| $($closure_body)*) }; // 匹配无参移动闭包 (move || $($closure_body:tt)*) => { do_sth(move || $($closure_body)*) }; // 兜底分支:普通表达式自动封装为闭包 ($expression:expr) => { do_sth(|| $expression) }; } // 测试用的do_sth函数 fn do_sth<F: FnOnce()>(f: F) { f(); } fn main() { generate_code!(println!("macro argument is expression")); generate_code!(|| println!("macro argument is closure")); }
如果需要支持带参数的闭包,只需要补充对应的匹配分支即可:
// 匹配带任意参数的非移动闭包 (|$($params:tt)*| $($closure_body:tt)*) => { do_sth(|$($params)*| $($closure_body)*) }; // 匹配带任意参数的移动闭包 (move |$($params:tt)*| $($closure_body:tt)*) => { do_sth(move |$($params)*| $($closure_body)*) };
注意事项
这种方案依赖Rust的语法规则:合法的Rust表达式中,|符号不会出现在表达式开头,只有闭包的参数列表会以|开头,因此不会出现普通表达式被误判为闭包的问题。
内容的提问来源于stack exchange,提问作者phip1611
相关产品推荐
相关产品推荐

