Search code examples
rustrust-macros

Different separators for the same variable in Rust Macros


I want to match a pattern like:

foo!(1,2,3;4,5,6;7,8,9); 

The same code would be generated for all numbers, but I'd want additional code to run when there's a semi-colon. Is this sort of pattern possible?

I've tried:

macro_rule! {
    foo ($($x:expr),*);*) => ...

But I can't seem to make that work on the right-hand side.


Solution

  • You never explained what the problem was with your existing code, so I don't know what to highlight in this example:

    macro_rules! foo {
        ($($($x:expr),*);*) => {
            $(
                $(
                    print!("{},", $x);
                )*
                println!("semi");
            )*
        }
    }
    
    fn main() {
        foo!(1,2,3;4,5,6;7,8,9); 
    }
    

    I can point out things from your original code:

    1. It's called macro_rules!, not macro_rule!
    2. The name of the macro being defined goes before the original {, not after.
    3. Like most programming, paired delimiters need to be evenly matched to be syntactically valid.

    The Rust Programming Language, first edition has several pieces of valuable information.

    Basic syntax for defining a macro is covered in the macros chapter; I strongly suggest you read the entire thing. It also links to the reference, which contains some more lower-level detail.

    The section most related to your question is:

    Repetition

    The repetition operator follows two principal rules:

    1. $(...)* walks through one "layer" of repetitions, for all of the $names it contains, in lockstep, and
    2. each $name must be under at least as many $(...)*s as it was matched against. If it is under more, it’ll be duplicated, as appropriate.