Search code examples
stringrustrust-macrosrust-decl-macros

How to return a new String from a declarative macro?


So here I am, trucking along with Rustlings, until I get broadsided with test 4.

It wants me to write a macro that will satisfy the following code:

fn main() {
    if my_macro!("world!") != "Hello world!" {
        panic!("Oh no! Wrong output!");
    }
}

So, I wrote this:

macro_rules! my_macro {
    ($val:expr) => {
        println!("Hello {}", $val);
    }
}

And Rustlings spat this out:

error[E0308]: mismatched types
  --> exercises/test4.rs:15:31
   |
15 |     if my_macro!("world!") != "Hello world!" {
   |                               ^^^^^^^^^^^^^^ expected (), found reference
   |
   = note: expected type `()`
              found type `&'static str`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.

Which, you know. I get. I understand what the problem is, but I don't understand how to write a macro that will satisfy the code. I can change the code I'm testing against, but that's not what the test wants me to do. I'm only to write a macro. I'm stumped. I also don't understand how encapsulating the macro in a module is meant to help, but the test says it's a test on modules as well as macros.


Solution

  • println! will print to the stdout. Instead, you just want to format the string and return it from the macro. Use format! instead, and drop the ; so that it will return the expression instead of ():

    macro_rules! my_macro {
        ($val:expr) => {
            format!("Hello {}", $val)
        }
    }