声明宏
Rust常用声明宏
println!
println!使用示例
#![allow(unused)] fn main() { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(print_internals, format_args_nl)] macro_rules! println { () => ($crate::print!("\n")); ($($arg:tt)*) => ({ $crate::io::_print($crate::format_args_nl!($($arg)*)); }) } }
writeln!
可以将内容输入到指定文件
cargo run --example raw_command > examples/raw_command_output.txt
eprintln!
示例
声明宏示意图
macro_rules!定义与使用
macro_rules!定义示例
#[macro_export] macro_rules! my_vec { // 没带任何参数的 my_vec,我们创建一个空的 vec // 注意,由于宏要在调用的地方展开,我们无法预测调用 // 者的环境是否已经 做了相关的 use,所以我们使用的 // 代码最好带着完整的命名空间。 () => { std::vec::Vec::new() }; // 处理 my_vec![1, 2, 3, 4] ($($el:expr),*) => ({ let mut v = std::vec::Vec::new(); $(v.push($el);)* v }); // 处理 my_vec![0; 10] ($el:expr; $n:expr) => { std::vec::from_elem($el, $n) } }
$($el:expr), *)
- 在声明宏中,条件捕获的参数使用 $ 开头的标识符来声明。
- 每个参数都需要提供类型,这里
expr
代表表达式,所以 $el:expr 是说把匹配到的表达式命名为 $el。 - $(…),* 告诉编译器可以匹配任意多个以逗号分隔的表达式,然后捕获到的每一个表达式可以用 $el 来访问。
- 由于匹配的时候匹配到一个 $(…)* (我们可以不管分隔符),在执行的代码块中,我们也要相应地使用 $(…)* 展开。
- 所以这句 $(v.push($el);)* 相当于匹配出多少个 $el就展开多少句 push 语句。
macro_rules!使用示例
fn main() { let mut v = my_vec![]; v.push(1); // 调用时可以使用 [], (), {} let _v = my_vec!(1, 2, 3, 4); let _v = my_vec![1, 2, 3, 4]; let v = my_vec! {1, 2, 3, 4}; println!("{:?}", v); println!("{:?}", v); // let v = my_vec![1; 10]; println!("{:?}", v); }