Provide enumerate and len for macro * and +

One sometimes needs to know the current index and/or the length of a repetition. There are clever but cludgy ways to achieve this, which make a macro even less readable.

It would be very useful and much easier for the macro engine to provide these values. I would suggest $.var for the index (at which point of the repetition are we) and $#var for the length (what number of elements are there.) These syntaxes are currently not possible, hence backwards compatible.

This should also work for nested repetitions, as shown in this example, which has an outer repeat of paren lists and an inner one of all but the 1st literal in each:

macro_rules! x {
    ($(($a:literal $($b:literal)+))+) => {
        $($(println!("{} ({}/{}) -- {} ({}/{})", $a, $.a, $#a, $b, $.b, $#b);)+)+
        //                .. ##         .. ##        ---  ---      ---  ---
    }
}
x!((27  4 5 6)
   (49  7 8 9 0));
27 (0/2) -- 4 (0/3)
27 (0/2) -- 5 (1/3)
27 (0/2) -- 6 (2/3)
49 (1/2) -- 7 (0/4)
49 (1/2) -- 8 (1/4)
49 (1/2) -- 9 (2/4)
49 (1/2) -- 0 (3/4)

See RFC 3086 and its tracking issue:

5 Likes

More concretely, here's how your macro could look: playground

macro_rules! x {
    ($(($a:literal $($b:literal)+))+) => {
        $($(println!("{} ({}/{}) -- {} ({}/{})",
            $a, ${index(1)}, ${length(1)}, $b, ${index()}, ${length()});)+)+
    }
}

Thanks for pointing it out! The tracking issue is beyond bewildering, especially as it seems to be changing over time.

This example you give here, however is clear and something I can grok. :grinning: