0

Specs:

I am building a simple macro to call an attribute on a struct when the attribute's name is passed in as a string, like so:

send!(struct, "title"); // => struct.title Works

So far the above code works, because "title" is entered in as a verbatim string literal. But to be useful I want to pass in a my_str identifier for a string literal and have it be treated like the string literal I passed in above (basically like how things work in a normal function).

let my_str = "title";

send!(struct, my_str); // => struct.title Doesn't Work

The code above gives me this error:

expected a string literal, a verbatim stringify! call, or a verbatim concat! call.

Here is the code for the send! macro I created.

macro_rules! send {
    ($obj:ident, $msg:expr) => {
        unstringify!(
            let $x = unstringify!($msg) in {
                $obj . $x
            } 
        )
    }
}

If the above code looks confusing let me explain. It is saying call unstringify! on $msg and assign to $x then output $obj . $x as the final result. It is NOT two unstringify! calls (refer to the unstringify! reference material for any questions on that)

I know other macros like Rust's println! macro can handle either literals passed in or variables and treats them as the same. How can I achieve this in the send! macro?

Randall Coding
  • 463
  • 5
  • 15
  • 3
    This isn't possible. What you need instead is to `match` on the value of the string. – eggyal Apr 13 '21 at 14:29
  • 1
    `my_str` doesn't *represent* anything inside a macro: it's not a variable, it's just the identifier `my_str`. If you want the value of a variable that's set at runtime, you can't get it at compile time. – trent Apr 13 '21 at 14:29
  • 1
    You seem to want reflection. This isn't really related to macros. – Denys Séguret Apr 13 '21 at 14:31
  • 1
    What could be possible with macros is to change the struct itself to have an additional function doing the mapping. But this would be a macro on the struct type definition, not on the call. – Denys Séguret Apr 13 '21 at 14:34
  • @trentcl If that is true, how can `println!()` handle variables like this `println!("My value {}", my_str)` and yield a result? – Randall Coding Apr 13 '21 at 14:54
  • 2
    `println!("{}", my_str)` expands to more code that contains the identifier `my_str`. It doesn't evaluate `my_str` at compile time, otherwise it wouldn't work at all with strings that come from user input. – trent Apr 13 '21 at 15:06
  • 1
    @RandallCoding: See the expansion of that `println!` macro invocation [here](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=3fd6a8bfcfb9bdabd7001b98d3312901). – eggyal Apr 13 '21 at 15:09
  • @trentcl & eggyal Thanks, that makes sense. – Randall Coding Apr 13 '21 at 15:19

0 Answers0