为什么这个 Rust HashMap 宏不再起作用了?

5

我之前使用的是:

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

要创建对象,就像这样:
let mut hm = map! {HashMap, "a string" => 21, "another string" => 33};

然而,这种方法似乎不再有效。编译器报告如下:
- 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};
                                     ^~~~~~~

宏定义有何变化导致这不再起作用?

下面的基本示例可以正常工作:

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

struct Blah;

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

看起来这是关于 {T:ident, $(...), +} 扩展如何处理的一些更改?

这里发生了什么?

2个回答

10
你缺少在 T 前面加上 $ 符号。

它没有。你的代码肯定有所改变了。 - Chris Morgan

0

这个怎么样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);
}

此外,使用{}macro_rules map {}表示它将返回一个项目。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接