How to use println macro to capture ident in a declarative macro?

macro_rules! test {
    ($foo:ident) => {
        println!("{$foo}");
    };
}

fn main() {
    let bar = 0;
    test!(bar);
}

Getting error message:

error: invalid format string: expected `'}'`, found `'$'`

Is there any way to use println macro to capture ident in a declarative macro?

Can't you just use the plain positional argument syntax?

macro_rules! test {
    ($foo:ident) => {
        println!("{}", $foo);
    };
}
macro_rules! test {
    ($foo:ident) => {
        let foo = $foo;
        println!("{foo}");
    };
}

fn main() {
    let bar = 0;
    test!(bar);
}

Careful, this makes the macro usable only in statement position (so no Some(foo) => test!(foo), branch, for instance).

To avoid that, have the macro emit braces ≠ the braces used to define the macro rules themselves. I personally thus use parenthesis to define the macro rules, since it's more symmetric (with the input of the macro), and makes the lack of surrounding braces more obvious:

macro_rules! test {(
    $foo:ident $(,)?
) => (
    {
        let foo = $foo;
        println!("{foo}");
    }
)}
2 Likes

A fair point. I was aware of the distinction but I figured it wasn't worth going into, particularly since the OP and @Cerber-Ursi 's version had a trailing semicolon which currently produces a warning that links to #79813. Maybe you are right that it is worth mentioning here though.

That's a neat idea I hadn't heard of before. I might adopt that myself.

1 Like