Unroll macro argument list?


#1

Is it possible to create a macro which unrolls its argument list and does something with it? I’m not looking for arithmetic unrolling (e.g., create n instances of some piece of an AST) but rather just syntactic unrolling. As a simple example, I’d like to be able to have something like:

unroll!((a, b),
        (c, d),
        (e, f),
        (g, h));

unroll to something like:

foo!(a, b);
foo!(c, d);
foo!(e, f);
foo!(g, h);

Is something like this possible?


#2

Sure thing! Here is an example where foo! just prints out the pairs of letters, but you can have it unroll to whatever you want.

macro_rules! foo {
    ($x:ident, $y:ident) => {
        println!(stringify!($x $y));
    }
}

macro_rules! unroll {
    ($($arg:tt),*) => {
        $(
            foo! $arg ;
        )*
    }
}

fn main() {
    unroll!((a, b),
            (c, d),
            (e, f),
            (g, h));
}

Here each comma-separated argument to unroll! gets matched as one $arg:tt, so for example $arg=(a, b). Then that becomes the argument to foo!, so foo!(a, b);.


#3

That’s fantastic; thanks so much!