Search code examples
arraysrustmacrosrust-macros

Rust macro for repeating array elements


I'm trying to write a Rust macro that fills up an array with repeating elements, in this case with zeros. This is what I came up with:

macro_rules! pad4  {
    () => {
        println!("0b00000000, 0b00000000, 0b00000000, 0b00000000");
    }
}

const arr: [u8; 8] = [pad4!(), 0b01111100, 0b10000010, 0b00000010, 0b01111110];

But I'm getting the following error:

expected `u8`, found `()`

Solution

  • Rust macros aren't simple string replacements, they pattern match over parsed tokens and must return Rust syntax that is valid in the context the macro is invoked in.

    Your current macro:

    macro_rules! pad4  {
        () => {
            println!("0b00000000, 0b00000000, 0b00000000, 0b00000000");
        }
    }
    

    Called in this context:

    const arr: [u8; 8] = [pad4!(), 0b01111100, 0b10000010, 0b00000010, 0b01111110];
    

    Expands to this:

    const arr: [u8; 8] = [
        {
            println!("0b00000000, 0b00000000, 0b00000000, 0b00000000");
        },
        0b01111100,
        0b10000010,
        0b00000010,
        0b01111110,
    ];
    

    Which is why you're getting an error, as the first expression block in the array returns () instead of the expected u8.

    You can use e.g. cargo expand to easily inspect the result of macro expansion.


    Here's pad4 but written in a way that works:

    macro_rules! pad4 {
        [$($e:expr),*] => {
            [0b00000000, 0b00000000, 0b00000000, 0b00000000, $($e,)*]
        }
    }
    
    const arr: [u8; 8] = pad4![0b01111100, 0b10000010, 0b00000010, 0b01111110];
    

    playground

    If you're brand new to Rust's declarative macros the go-to resource to learn them in-depth is The Little Book of Rust Macros.