1

Consider the following snippet:

macro_rules! quick_hello {
    ($to_print:expr) => {
        {
            let h = "hello";

            println!("{}", $to_print)
        }
    }
}

fn main() {
    quick_hello!(h);
}

If I compile it, I get:

error[E0425]: cannot find value `h` in this scope
  --> src/main.rs:12:18
   |
12 |     quick_hello!(h);
   |                  ^ not found in this scope

But shouldn't the quick_hello call in main expand to a block containing the let h = "hello" statement, thus allowing me to use it as a quickhand for "hello" at call site?

I might get that this is done to keep macros hygienic, but what if I require the above mentioned behaviour? Is there a way to "turn off" hygiene to achieve this?

trent
  • 25,033
  • 7
  • 51
  • 90
Dincio
  • 1,010
  • 1
  • 13
  • 25
  • And what should your macro do if you had variable named `h` at its call site? – Cerberus Sep 17 '20 at 13:10
  • @Cerberus override it with its new value (in this case "hello"). I am aware that this might not be the best choice design-wise, because it would look weird (maybe there could be a compiler warning to make it bearable?). Still it would save me a lot of typing in my use case, so I am still interested in this. – Dincio Sep 17 '20 at 13:44
  • You can just match a token `h` in a declarative macro. So [this](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=5f3bac51a0e2e21d5117a6e9050413c1) does what I assume you were going for, but it is hygienic (just kind of weird, syntax-wise). Don't reach for complicated and tricky when simple will do. If that does not apply to your real use case, consider asking a question about your real problem -- this example might be too simplistic to exhibit the problem you're facing. – trent Sep 17 '20 at 21:02
  • [(possibly relevant tweet)](https://twitter.com/pcwalton/status/1294676975575896064) Rust is pretty powerful already without macros, and *really* darn powerful even with hygienic macros -- before you decide you need even more power than that, consider other options. – trent Sep 17 '20 at 21:14
  • @Cerberus Yes I think I might have oversimplified my problem... Because your approach does help me to achieve the wanted behaviour here, but would be too complicated when tackling my real problem (where the "shorthand variable" is used in multiple places). Should I edit the question or terminate it and make a new one? – Dincio Sep 18 '20 at 21:28
  • @trentcl I am pretty sure that I would simplify my code a great deal with macros, but again I see now that it's difficult to understand this without an explanation of my actual problem – Dincio Sep 18 '20 at 21:30

2 Answers2

1

To process quick_hello call rustc is looking up for a valid expression for $to_print:expr. But h is not a valid expression at that context so rustc doesn't move forward with the macro implementation and prints the error.

MaxV
  • 2,601
  • 3
  • 18
  • 25
  • I am aware of this, I was wandering if there was a way of achieving my desired behaviour. – Dincio Sep 18 '20 at 21:31
  • 1
    `Is there a way to "turn off" hygiene to achieve this?` It's not about hygiene at all. The `quick_hello::h` variable doesn't exist before `quick_hello` is called. To call the macros you have to have a valid expression. But `quick_hello!(h);` is not a valid expression in the context for any case of `quick_hello`. You can add another case where `quick_hello`'s parameter will have another type. Then it may work. Finally it's not clear what you're trying to achieve. – MaxV Sep 21 '20 at 18:55
0

As people above have noted, it is not clear what you want this macro to do. However, this compiles and prints hello:

macro_rules! quick_hello {
    (h) => {
    let h = "hello";
      println!("{}", h)  
    };
    ($to_print:expr) => {
        {
            println!("{}", $to_print)
        }
    }
}
fn main() {
    quick_hello!(h);
}
Satsu
  • 24
  • 1
  • Yes, I also see now that the example I give is too simple to convey what I wanto to achieve. I will try to close the question. – Dincio Sep 29 '20 at 16:04
  • This is actually the first time this happens to me and I am not sure of what I should do... I think I will accept your answer (as it actually sovles the problem) and create a separate more specific question. – Dincio Sep 29 '20 at 16:08