4

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.

Peter Hall
  • 53,120
  • 14
  • 139
  • 204
AerosolSP
  • 177
  • 1
  • 1
  • 10

1 Answers1

5

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)
    }
}
Peter Hall
  • 53,120
  • 14
  • 139
  • 204
  • That's what I was looking for. The issue I was having was I couldn't figure out how to make it evaluate to "Hello world!" without creating new variables, which you can't do. Bravo Mr. Hall, and much appreciated. – AerosolSP Feb 28 '19 at 17:32
  • 1
    @AerosolSP there is no reason you can't create new variables. The branch of the macro has to just be a single expression (i.e. if you create a variable and do something with it, the whole expression must be enclosed in braces): https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=06545da95b31cb540a58a4b21af23d7b Think about how the vec! macro works. It has to create a new vector: https://doc.rust-lang.org/1.7.0/book/macros.html – ObliqueMotion Feb 28 '19 at 17:39
  • 1
    That being said, using the format! macro is still a much cleaner solution. I just want to make sure you don't think that you can't create a variable in a macro. – ObliqueMotion Feb 28 '19 at 17:40
  • @ObliqueMotion I think the confusion might be from the fact that you can't create a variable in a macro that you then use _outside_ of the macro. – Peter Hall Feb 28 '19 at 17:42
  • @ObliqueMotion thanks a lot for that clarification. I thought the Rustlings course would be a bit more thorough, but I'm beginning to realize I should've gone through the book first! – AerosolSP Feb 28 '19 at 17:46