编写自定义格式的最佳方式是什么!宏观?
What's the best way to write a custom format! macro?
我正在尝试创建一个自定义 crash!
宏,它基本上只是包装 eprintln!
,但它可以是任何其他类似 format!
的宏。目前看起来像这样。
macro_rules! crash {
($fmt_str:literal, $($args:expr),*) => {{
eprintln!($fmt_str, $args);
std::process::exit(1);
}};
}
我不能直接使用 $args
,因为它还在重复,所以我需要一些方法来将它分开,但我不确定该怎么做。
原来我只是脑子一片空白,最后回答了我自己的问题。我只需要扩展 $args
... 对于最终来到这里的其他人,解决方案如下所示:
macro_rules! crash {
($fmt_str:literal) => {{
eprintln!($fmt_str);
std::process::exit(1);
}};
($fmt_str:literal, $($args:expr),*) => {{
eprintln!($fmt_str, $($args),*);
std::process::exit(1);
}};
}
虽然您的解决方案有效,但转发宏参数的最佳方式是将它们捕获为 tt
。在你的情况下,因为你想要的只是转发它们,你可以使用 $($t:tt)*
:
macro_rules! crash {
($($t:tt)*) => {{
eprintln!($($t)*);
std::process::exit(1);
}};
}
这样做的好处是它是完全透明的,并且可以启用底层宏启用的所有功能。例如,在这种情况下,tt
版本支持 early-expanded 格式字符串,而您的原始版本不支持 (playground):
// crash!(concat!("a", "b")); // Does not compile
crash_tt!(concat!("a", "b"));
我正在尝试创建一个自定义 crash!
宏,它基本上只是包装 eprintln!
,但它可以是任何其他类似 format!
的宏。目前看起来像这样。
macro_rules! crash {
($fmt_str:literal, $($args:expr),*) => {{
eprintln!($fmt_str, $args);
std::process::exit(1);
}};
}
我不能直接使用 $args
,因为它还在重复,所以我需要一些方法来将它分开,但我不确定该怎么做。
原来我只是脑子一片空白,最后回答了我自己的问题。我只需要扩展 $args
... 对于最终来到这里的其他人,解决方案如下所示:
macro_rules! crash {
($fmt_str:literal) => {{
eprintln!($fmt_str);
std::process::exit(1);
}};
($fmt_str:literal, $($args:expr),*) => {{
eprintln!($fmt_str, $($args),*);
std::process::exit(1);
}};
}
虽然您的解决方案有效,但转发宏参数的最佳方式是将它们捕获为 tt
。在你的情况下,因为你想要的只是转发它们,你可以使用 $($t:tt)*
:
macro_rules! crash {
($($t:tt)*) => {{
eprintln!($($t)*);
std::process::exit(1);
}};
}
这样做的好处是它是完全透明的,并且可以启用底层宏启用的所有功能。例如,在这种情况下,tt
版本支持 early-expanded 格式字符串,而您的原始版本不支持 (playground):
// crash!(concat!("a", "b")); // Does not compile
crash_tt!(concat!("a", "b"));