# Map! macro as a HashMap counter of vec!

**URL:** <https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720>\
**Category:** language design\
**Created:** [May 30, 2022, 8:39pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720 "2022-05-30T20:39:18Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![simbleau](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/simbleau/32/9053_2.png) [@simbleau](https://internals.rust-lang.org/u/simbleau)\
**Post date:** [May 30, 2022, 8:39pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/1 "2022-05-30T20:39:18Z")

</div>

I could not find any plans to introduce a `map!` macro, similar to `vec!`. Perhaps it's been pitched under a different name. I would like to get input on this, as I think the usefulness is perhaps obvious; I was a a bit surprised to see a lack of optics on this already.

Here's a discrete use case one might have:

```rust
    primes = map! {
     'a' => 2,
     'b' => 3,
     'c' => 5,
     'd' => 7,
     'e' => 11,
     'f' => 13,
     'g' => 17,
     'h' => 19,
     'i' => 23,
     'j' => 29,
     'k' => 31,
     'l' => 37,
     'm' => 41,
     'n' => 43,
     'o' => 47,
     'p' => 53,
     'q' => 59,
     'r' => 61,
     's' => 67,
     't' => 71,
     'u' => 73,
     'v' => 79,
     'w' => 83,
     'x' => 89,
     'y' => 97,
     'z' => 101
    };

```

Where someone could use this prime map to encode (lowercase, for brevity) strings, such as testing if two strings are anagrams of one another.

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://internals.rust-lang.org/u/chrefr)\
**Post date:** [May 30, 2022, 8:42pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/2 "2022-05-30T20:42:59Z")

</div>

> <https://github.com/rust-lang/rfcs/issues/542>
>
> \<a href="https://github.com/gsingh93"\>\<img src="https://avatars.githubuserconten…t.com/u/1012677?v=3" align="left" width="96" height="96" hspace="10"\>\</img\>\</a\> \*\*Issue by \[gsingh93\](https://github.com/gsingh93)\*\*
> \_Saturday Jun 07, 2014 at 16:49 GMT\_
> 
> \_For earlier discussion, see https://github.com/rust-lang/rust/issues/14726\_
> 
> \_This issue was labelled with: A-syntaxext in the Rust repository\_
> 
> \---
> 
> I wanted to create an issue first asking about this before submitting a pull request.
> 
> Can I go ahead an implement \`hashmap!()\`, \`hashset!()\`, \`treemap!()\`, and \`treeset!()\` macros for constructing those collections with the given arguments? The syntax would be:
> 
> \`\`\`
> let h = hashmap!("foo" =\> "bar");
> let s = hashset!("foo");
> \`\`\`
> 
> I already have these macros implemented in my own projects, so I'd just have to add them to macros.rs.
> 
> If I can add these, is there a process for testing macros? Or would I just replace all occurrences of hash{map,set} and tree{map,set} creation in the tests by the macros?

I think this is just not as often needed as `vec![]`, and with const generics we have `From` impls that are just as short, and don't require any macro: `HashMap::from([("key", "value"), ("k2", "v2")])`;

Oh, and [there is a crate for that](https://crates.io/crates/maplit) (probably more than one).

---

<div class="post-metadata">

**Author:** ![simbleau](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/simbleau/32/9053_2.png) [@simbleau](https://internals.rust-lang.org/u/simbleau)\
**Post date:** [May 30, 2022, 8:54pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/3 "2022-05-30T20:54:44Z")

</div>

I'm going to contest the idea it's not needed as often. Maps and Vecs are the standard of common data structures. Think of the relative pervasiveness of `{}` and `[]` in python.

The same syntax you mention is just as short and exists for Vec (`Vec::from(...)`) but yet we have the `vec!` macro. I agree it is not as popular as Vec, but I think it deserves the macro. Behind Vec, HashMap would be the 2nd most important and used data structure.

I know this could lead to a slippery slope of "Now we need a `btreemap!` and a `heap!`", but for the time being, I think the prevalence of HashMap would justify such a macro into prelude/std.

Talk me out of it. But I still like the idea of this as a macro in the prelude.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [May 30, 2022, 9:11pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/4 "2022-05-30T21:11:37Z")

</div>

> [@simbleau](#):
>
> Think of the relative pervasiveness of `{}` in python.

Except in python, _everything_ is a map (dict). A majority of `{}` uses in python shouldn't be `hashmap!{}` in rust, but rather `Struct {}`.

> [@simbleau](#):
>
> The same syntax you mention is just as short and exists for Vec ( `Vec::from(...)` ) but yet we have the `vec!` macro.

Two reasons for `vec!` to exist that don't apply to `hashmap!`:

- We have array literals, and `vec` is _the_ growable array type, so should have equivalent syntax.
- `vec!` existed before const generics did, so `Vec::from([T; N])` was limited to 32 elements.

The biggest argument is the former imho: array literals have a known syntax, but we don't have an existing syntax for maps. As such, there's multiple possible syntaxes for a `map!` macro: `{ key: val }` struct-like, `{ key => val }` match-like, `[(key, val)]` collect-like, etc.

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://internals.rust-lang.org/u/chrefr)\
**Post date:** [May 30, 2022, 9:13pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/5 "2022-05-30T21:13:06Z")

</div>

> [@simbleau](#):
>
> The same syntax you mention is just as short and exists for Vec ( `Vec::from(...)` ) but yet we have the `vec!` macro. I agree it is not as popular as Vec, but I think it deserves the macro. Behind Vec, HashMap would be the 2nd most important and used data structure.

Besides the two reasons @CAD97 mentioned, there are another two:

1. `vec![]` also has the repeat syntax `[v; n]`, `map!` won't.
2. `Vec`s are still _far_ more common than maps.

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://internals.rust-lang.org/u/chrefr)\
**Post date:** [May 30, 2022, 9:13pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/6 "2022-05-30T21:13:57Z")

</div>

> [@CAD97](#):
>
> { key: val }

Unlikely, because it will require parentheses around expressions. But the point still holds.

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [May 30, 2022, 9:14pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/7 "2022-05-30T21:14:42Z")

</div>

> [@simbleau](#):
>
> Behind Vec, HashMap would be the 2nd most important and used data structure.

I think I end up using `BTreeMap` more myself. In my experience, I have vectors of static data in literal code _way_ more than maps. And the times I do, the `from` family of functions work fine (though vectors of tuples can be better if it can keep the data in a few cache lines instead of spread in a web across the heap). How big of a "map literal" is being considered here?

The syntax is also up for debate. Python-like `:`, PHP-like `=>`, or something else completely?

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://internals.rust-lang.org/u/chrefr)\
**Post date:** [May 30, 2022, 9:15pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/8 "2022-05-30T21:15:11Z")

</div>

This is fifth reason: we have _two_ kinds of maps.

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [May 30, 2022, 9:18pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/9 "2022-05-30T21:18:02Z")

</div>

Not just two, an infinite number since hash map is parameterized by its hasher.

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://internals.rust-lang.org/u/chrefr)\
**Post date:** [May 30, 2022, 9:19pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/10 "2022-05-30T21:19:14Z")

</div>

My instinct is to say that `Vec` is also parameterized by an allocator, but we replace the hasher far more than we replace tha allocator.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [May 30, 2022, 9:25pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/11 "2022-05-30T21:25:08Z")

</div>

> [@chrefr](#):
>
> > [@CAD97](#):
> >
> > { key: val }
> 
> Unlikely, because it will require parentheses around expressions.

Not if expression type ascription doesn't exist.

* * *

Also, it's worth noting that a lot of people are moving to support the opinion that you should prefer an ordered collection over an unordered one until performance metrics indicate that the performance benefit of (effectively) nondeterministic iteration order outweighs the downsides of unpredictable ordering.

Having `hashmap!` but not `indexmap!` or `btreemap!` hinders this.

* * *

Ultimately what I find myself falling back to as the appropriate macro is instead based on `collect`/`FromIterator`.

```rust
macro_rules! collect {
    [$($e:expr),* $(,)?] => {
        [$($e),*].into_iter().collect()
    }
}

```

... but also with how little that macro does, it's not really worth having the macro over just using `from` or [`from_iter`](https://doc.rust-lang.org/stable/std/collections/hash_map/struct.HashMap.html#method.from_iter) instead, which have the benefit of the inbuilt type hint.

(`FromIterator` is added to the prelude by edition 2021.)

---

<div class="post-metadata">

**Author:** ![simbleau](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/simbleau/32/9053_2.png) [@simbleau](https://internals.rust-lang.org/u/simbleau)\
**Post date:** [May 30, 2022, 9:30pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/12 "2022-05-30T21:30:13Z")

</div>

I think you had some really solid points CAD.

However what you said last I don't agree with, particularly "how little that macro does, it's not really worth having the macro". A majority of people probably don't want to touch Rust macros with a 50 foot pole. Rust and Rust Macros are literally two different languages.

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://internals.rust-lang.org/u/chrefr)\
**Post date:** [May 30, 2022, 9:32pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/13 "2022-05-30T21:32:51Z")

</div>

> [@simbleau](#):
>
> However what you said last I don't agree with, particularly "how little that macro does, it's not really worth having the macro". A majority of people probably don't want to touch Rust macros with a 50 foot pole. Rust and Rust Macros are literally two different languages.

That is why people have built crates for that.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [May 30, 2022, 9:37pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/14 "2022-05-30T21:37:46Z")

</div>

> [@simbleau](#):
>
> However what you said last I don't agree with, particularly "how little that macro does, it's not really worth having the macro". A majority of people probably don't want to touch Rust macros with a 50 foot pole.

To be clear, what I'm suggesting isn't for people to rewrite the macro, but just to call `from` or `from_iter` instead. It's literally the difference between

```rust
let _: IndexMap = collect![("a", "b"), ("c", "d")];
// the type hint is required

```

and

```rust
let _ = IndexMap::from([("a", "b"), ("c", "d")]);
// or maybe it requires
let _ = IndexMap::from_iter([("a", "b"), ("c", "d")]);

```

That's not worth a macro imho.

---

<div class="post-metadata">

**Author:** ![simonbuchan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/simonbuchan/32/9390_2.png) [@simonbuchan](https://internals.rust-lang.org/u/simonbuchan)\
**Post date:** [June 1, 2022, 3:29pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/15 "2022-06-01T15:29:16Z")

</div>

There are a whole bunch of crates out there that do this, I like [https://crates.io/crates/velcro](https://crates.io/crates/velcro)

It would be nice to have a const map though. You can make your own without too much effort, I guess (if performance or ergonomics don't matter too much)

---

<div class="post-metadata">

**Author:** ![toc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/toc/32/6692_2.png) [@toc](https://internals.rust-lang.org/u/toc)\
**Post date:** [June 1, 2022, 4:00pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/16 "2022-06-01T16:00:57Z")

</div>

> [@CAD97](#):
>
> `let _ = IndexMap::from([("a", "b"), ("c", "d")]);`

There is an example of this in [the examples section of hashmap](https://doc.rust-lang.org/std/collections/struct.HashMap.html#examples), but perhaps it should be part of the first example. Similarly [in the book](https://doc.rust-lang.org/stable/book/ch08-03-hash-maps.html), hash maps are only constructed via `mut`/`insert`.

And honestly other than repeated clones `vec!` could just be `Vec::from([a, b, c])` most of the time. I can certainly understand where someone could get the ideas that

- to construct a `Vec`: use the magic/convenient `vec!` macro
- to construct a `Map`: use `mut` and a bunch of verbose inserts (why is it this inconvenient)

without happening upon `HashMap::from`.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [August 30, 2022, 4:00pm UTC](https://internals.rust-lang.org/t/map-macro-as-a-hashmap-counter-of-vec/16720/17 "2022-08-30T16:00:58Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
