3 ms·
> Alas, counting in macro by example is possible, but not trivial. It's not stabilized yet, but RFC3086[1] introduces macro metavariable expressions, which mak
by efaref 5y ago
> Alas, counting in macro by example is possible, but not trivial.
It's not stabilized yet, but RFC3086[1] introduces macro metavariable expressions, which make counting trivial!
The example macro becomes:
macro_rules! define_error {
($($err:ident,)*) => {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Error {
$($err,)*
}
impl Error {
pub fn from_code(code: u32) -> Option<Error> {
match code {
$( ${index()} => Some(Error::$err), )*
_ => None,
}
}
}
};
}
You can see this in practice on the playground[2].
[1]: https://github.com/rust-lang/rfcs/blob/master/text/3086-macro-metavar-expr.md https://github.com/rust-lang/rfcs/blob/master/text/3086-macr...
[2]: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=20ddadf7a570c0cb6d2f1deadef3c344 https://play.rust-lang.org/?version=nightly&mode=debug&editi...
- codeflo 5y agoThanks for the link, that seems very useful. I recently had to work around this by transforming a list (a, b, c, d) into something like 1+1+1+1+0 to get a count. What this RFC proposes looks so much less painful.
- afdbcreid 5y agoThere's much cooler approach: https://veykril.github.io/tlborm/decl-macros/building-blocks/counting.html#bit-twiddling https://veykril.github.io/tlborm/decl-macros/building-blocks.... macro_rules! count { () => (0); ($odd:tt ($a:tt $b:tt)*) => ((count!($($a)*) << 1) | 1); (($a:tt $b:tt)*) => (count!($($a)*) << 1); } It uses bit twiddling to avoid generating very big AST and eventually crashing the compiler. Though I have to admit using `${count()}` is better.