文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
10.2 宏
宏是一种元编程技术,用代码生成代码。
- 直接展开(expand)到调用处。
- 生成代码,灵活性非泛型可比。
- 缺点是不便于调试。
macro_rules! name { (pattern1) => (template1); (pattern2) => (template2); ... }
macro_rules! say_hello { () => ( println!("Hello!"); ); } fn main() { say_hello!(); // 也可写成 say_hello![] 或 say_hello!{}。 }
添加参数,并标注其类型。
参数以
$
为前缀,ident
表明类型是标识符,比如函数或变量名。
macro_rules! say_hello { ($s: ident) => ( println!("hello, {}!", $s); ); } fn main() { let s = "world!"; say_hello!(s); }
macro_rules! create_add { ($name: ident, $type: ty) => ( fn $name(x: $type, y: $type) -> $type { x + y } ); } create_add!(add1, i32); create_add!(add2, f32); fn main() { add1(1, 2); add2(1.1, 1.2); }
像 match 那样,分支匹配。
macro_rules! test { ($one: expr) => ( println!("{:?}", $one); ); ($one: expr, $two: expr) => ( println!("{:?}, {:?}", $one, $two); ); } fn main() { test!(1 + 1); test!(1 + 1, 2); }
接受变参,递归展开。
macro_rules! test { ($one: expr) => ( println!("{:?}", $one); ); ($one: expr, $($two: expr),+) => ( // + 表示 1 到多个。 test!{ $one } // 递归调用,用大括号。 test!{ $($two),+ } ); } fn main() { test!(1 + 1); test!(1 + 2, 4, 3 * 4); }
内置宏
由编译器提供。
file!
,line!
,column!
cfg!
env!
导入导出
宏在编译前期被展开。
- 模块中的宏,对子模块可见。可直接以名称调用,无需全路径。
// main.rs macro_rules! say_hello { () => ( println!("Hello!"); ); } pub mod a { pub mod b { pub fn test() { say_hello!(); // 子模块可见 !!! } } } fn main() { a::b::test(); }
- 使用
#[macro_use] mod
,将子模块内的宏导出到当前模块。
// util.rs macro_rules! elapsed { // 无需 pub !!! ($e: expr) => ( use std::time::Instant; let now = Instant::now(); { $e; } println!("elapsed: {:?}", now.elapsed()); ); }
// main.rs #[macro_use] mod util; // 导出 util 内的宏,无需额外 use 导入。 fn main() { elapsed!({ println!("hello, world!"); }); }
- 使用
#[macro_export]
标记宏,自动导出到根模块。
// util.rs #[macro_export] macro_rules! elapsed { // 无需 pub !!! ($e: expr) => ( use std::time::Instant; let now = Instant::now(); { $e; } println!("elapsed: {:?}", now.elapsed()); ); }
// main.rs mod util; fn main() { elapsed!({ println!("hello, world!"); }); }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论