Macros

The problem was taken from exercism and my solution you can find on git repo Codeberg.

Problem Statement

You can produce a Vec of arbitrary length inline by using the vec![] macro. However, Rust doesn't come with a way to produce a HashMap inline. Rectify this by writing a hashmap!() macro.

For example, a user of your library might write hashmap!('a' => 3, 'b' => 11, 'z' => 32). This should expand to the following code:

#![allow(unused)]
fn main() {
{
   let mut hm = HashMap::new();
   hm.insert('a', 3);
   hm.insert('b', 11);
   hm.insert('z', 32);
   hm
}
}

Note that the maplit crate provides a macro which perfectly solves this exercise. Please implement your own solution instead of using this crate; please make an attempt on your own before viewing its source.

Note that this exercise requires Rust 1.36 or later.

Solution

Macro is simple. It is just a modification of the code from the book The Rust programming Language. The tricky is only the macromatcher ( $( $key:expr => $val:expr ),+ $(,)? ) because according to the tests we want both hashmap!(23=> 623, 34 => 21) and hashmap!(23 => 623, 34 => 21,) (with comma after last expression) to work.


#[macro_export]
macro_rules! hashmap {
    ( $( $key:expr => $val:expr  ),+ $(,)? ) => { {
        let mut temp_map = ::std::collections::HashMap::new();
            $(
                temp_map.insert($key,$val);
                )*
            temp_map
        }
    };
    () => {
        ::std::collections::HashMap::new();
    };
}