I can't find a crate with a simple count_tts macro. Example: count_tts!(a b c) == 3. Is there one out there? Would it be useful if I published one? If yes, please read on and review my code.
I found this post by @tobia which seems to be the best implementation. But I made a couple changes. I removed the usize annotations. Since the expansion is logarithmic, I don't think this will present an issue with type inference slowness. I also reduced recursion for odd cases.
Does this qualify as a one-size-fits-all solution?
I personally don't think it is useful in a crate. Maybe in a macro snippets collection.
(I copied this from one of my crates and modified it to fit this usecase.)
Note that your version is linear in the number of tts, unlike the ones above, which are logarithmic. For example, when counting a sequence of length 128, your version will expand to 128 operations, while the other versions will only use 7 operations.
For cases where the size of the expansion matters, it does seem useful to publish the efficient version in a crate for re-use.
Careful, you forgot to $crate:: qualify your recursive calls to the macro.
This means that a user doing:
fn main ()
{
let _ = ::count_tts::count_tts!( will fail );
}
would get an error.
Tip: when testing a macro that will be exported, use integration tests. Ideally two: one that uses #[macro_use] extern crate ... and another that just uses fully-qualified macro calls like in my example .
Aside
If we are to use a dedicated crate to export a macro that does this, I personally would prefer if it were done with a procedural macro:
This has the ever diminishing drawback of requiring Rust 1.45.0, but has the advantage of yielding a far more readable cargo expand-ed code, which is not to be underestimated.
Thank you for the tips, @Yandros ! Darn, I was so proud of my macro_rules! but I have to agree the procedural macro is better. I will update the crate.