5

I previously used:

#[macro_export]
macro_rules! map(
  { T:ident, $($key:expr => $value:expr),+ } => {
    {
      let mut m = $T::new();
      $(
        m.insert($key, $value);
      )+
      m
    }
 };
)

To create objects, like this:

let mut hm = map! {HashMap, "a string" => 21, "another string" => 33};

However, this no longer seems to work. The compiler reports:

- Failed:
macros.rs:136:24: 136:31 error: no rules expected the token `HashMap`
macros.rs:136     let mut hm = map! {HashMap, "a string" => 21, "another string" => 33};
                                     ^~~~~~~

What's changed with macro definitions that makes this no longer work?

The basic example below works fine:

macro_rules! foo(
  {$T:ident} => { $T; };
)

struct Blah;

#[test]
fn test_map_create() {
  let mut bar = foo!{Blah};
}

So this seem to be some change to how the {T:ident, $(...), +} expansion is processed?

What's going on here?

Doug
  • 32,844
  • 38
  • 166
  • 222

2 Answers2

10

You’re lacking the $ symbol before T.

Chris Morgan
  • 86,207
  • 24
  • 208
  • 215
0

How about this play.rust-lang.org?

// nightly rust
#![feature(type_name_of_val)]
use std::collections::{BTreeMap, HashMap};

macro_rules! map {
    ($T:ty; $( $key:literal : $val:expr ),* ,) => {
        {
            // $T is the full HashMap<String, i32>, <$T> is just HashMap
            let mut m: $T = <$T>::new();
            $(
            m.insert($key.into(), $val);
            )*
            m
        }
    };
    // handle no tailing comma
    ($T:ty; $( $key:literal : $val:expr ),*) => {
        map!{$T; $( $key : $val ,)*}
    }
}

fn main() {
    let hm = map! {HashMap<String, i32>;
        "a": 1,
        "b": 2,
        "c": 3,
    };
    let bm = map! {BTreeMap<String, i32>;
        "1": 1,
        "2": 2,
        "3": 3
    };

    println!("typeof hm = {}", std::any::type_name_of_val(&hm));
    println!("typeof bm = {}", std::any::type_name_of_val(&bm));
    dbg!(hm, bm);
}

Additional, use {}, macro_rules map {} means it will return an item