# Should HashMap be added to std prelude?

**URL:** <https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717>\
**Category:** libs\
**Created:** [August 16, 2019, 5:19am UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717 "2019-08-16T05:19:19Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![tesuji](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tesuji/32/12790_2.png) [@tesuji](https://internals.rust-lang.org/u/tesuji)\
**Post date:** [August 16, 2019, 5:19am UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/1 "2019-08-16T05:19:19Z")

</div>

Continuing the discussion from [Should the Future trait be part of the prelude](https://internals.rust-lang.org/t/should-the-future-trait-be-part-of-the-prelude/10669/9):

_Poll ([view on site](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/1))_

The PR to add HashMap to std's prelude: [https://github.com/rust-lang/rust/pull/63418](https://github.com/rust-lang/rust/pull/63418)

---

<div class="post-metadata">

**Author:** ![HadrienG](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hadrieng/32/3294_2.png) [@HadrienG](https://internals.rust-lang.org/u/HadrienG)\
**Post date:** [August 16, 2019, 6:36am UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/2 "2019-08-16T06:36:59Z")

</div>

On one hand, it seems strange that Vec is in the prelude and HashMap isn't. On the other hand, it has been said before that one difference between the two is that there are multiple good ways to implement a HashMap, depending on the use case.

---

<div class="post-metadata">

**Author:** ![Centril](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/centril/32/3334_2.png) [@Centril](https://internals.rust-lang.org/u/Centril)\
**Post date:** [August 16, 2019, 6:44am UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/3 "2019-08-16T06:44:57Z")

</div>

> [@HadrienG](#):
>
> On the other hand, it has been said before that one difference between the two is that there are multiple good ways to implement a HashMap, depending on the use case.

I think there are more good ways to implement a HashMap than a Vec but you can still make design decisions about the latter in terms of e.g. the multiplying factor to use when reallocating.

---

<div class="post-metadata">

**Author:** ![nicoburns](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nicoburns/32/2313_2.png) [@nicoburns](https://internals.rust-lang.org/u/nicoburns)\
**Post date:** [August 16, 2019, 8:30am UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/4 "2019-08-16T08:30:42Z")

</div>

I think yes, and that BtreeMap ought to be in there too.

---

<div class="post-metadata">

**Author:** ![aschampion](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aschampion/32/3645_2.png) [@aschampion](https://internals.rust-lang.org/u/aschampion)\
**Post date:** [August 16, 2019, 10:48am UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/5 "2019-08-16T10:48:19Z")

</div>

If it were added to the prelude, putting a `hashmap!` literal macro like the one in `maplit` in std would make sense for parity with `Vec`/`vec!`.

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [August 16, 2019, 2:18pm UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/6 "2019-08-16T14:18:13Z")

</div>

> [@nicoburns](#):
>
> I think yes, and that BtreeMap ought to be in there too.

I strongly agree with this, and think it would be bad to give `HashMap` special status which would lead to people picking it over `BTreeMap` without due consideration:

[https://twitter.com/bascule/status/1156720845152108544](https://twitter.com/bascule/status/1156720845152108544)

---

<div class="post-metadata">

**Author:** ![jessa0](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jessa0/32/7802_2.png) [@jessa0](https://internals.rust-lang.org/u/jessa0)\
**Post date:** [August 16, 2019, 3:16pm UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/7 "2019-08-16T15:16:51Z")

</div>

BTreeMap, on the other hand, is so complex that I haven't seen (and don't expect) many others even try to write an alternative implementation..

I would actually suggest a more general-purpose Map type to be in the prelude which is optimized by default for a small number of keys (say, a dozen). Erlang did this, through for reasons that may not apply to Rust. I would suspect the winner in std for small number of keys would be BTreeMap, but we'd want to benchmark that.

---

<div class="post-metadata">

**Author:** ![nugend](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nugend/32/1684_2.png) [@nugend](https://internals.rust-lang.org/u/nugend)\
**Post date:** [August 16, 2019, 4:02pm UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/8 "2019-08-16T16:02:41Z")

</div>

Can someone who knows macros better tell me if this is a workable idea or not:

Would it be possible to make a macro that builds an associative array trait object (which could default to Hashmap as the implementation type) which works like the following:

```rust
let d1 = dict!("key"=>"Value"); // type is trait object AssociativeArray
let d2 = dict!(std::collections::HashMap,"key"=>"Value"); // type is std::collections::HashMap
let d3:std::collections::BTreeMap<_,_> = dict!("key" => "Value"); // type is std::collections::BTreeMap
let d4 = dict!(d1,"key"=>"NewValue"); // takes ownership of d1, inserts keys into AssociativeArray

```

Maybe the skip the last one. I'm not sure.

This suggestion would preclude the introduction of a such a trait, which, given its absence, maybe there's a good reason for not having and therefore this entire suggestion is moot?

edit: Not sure why I was thinking trait objects, I think the first return could just be `impl AssociativeArray`

---

<div class="post-metadata">

**Author:** ![ExpHP](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/exphp/32/6208_2.png) [@ExpHP](https://internals.rust-lang.org/u/ExpHP)\
**Post date:** [August 16, 2019, 4:10pm UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/9 "2019-08-16T16:10:57Z")

</div>

If we have the maps, we should have the sets, too.

---

<div class="post-metadata">

**Author:** ![djc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/djc/32/1592_2.png) [@djc](https://internals.rust-lang.org/u/djc)\
**Post date:** [August 16, 2019, 4:50pm UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/10 "2019-08-16T16:50:19Z")

</div>

One way to gain more objective insight on this would be to analyze the crater collection of source code (IIRC someone already made something like this available?) and search for all usages of `std::`.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [August 16, 2019, 5:45pm UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/11 "2019-08-16T17:45:54Z")

</div>

I agree that HashSet belongs in the prelude too.

---

<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:** [August 16, 2019, 7:13pm UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/12 "2019-08-16T19:13:52Z")

</div>

Both of the standard map types implement `FromIterator<(K, V)>` ([`HashMap`](https://doc.rust-lang.org/std/collections/struct.HashMap.html#impl-FromIterator%3C(K%2C%20V)%3E), [`BTreeMap`](https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#impl-FromIterator%3C(K%2C%20V)%3E)). So for dictionary literals up to 32 items long, you can use `[($key, $value),*].into_iter().collect()`. For the insertion, `Extend<(K, V)>` (`map.extend(iter::once(($key, $value)))`), which is basically `collect_to`.

So yes, the macro would be practical, so long as you always provide the concrete type somehow. I'm pretty sure someone's written a `collect!` macro that does this.

Collection traits have been discussed [many times](https://internals.rust-lang.org/t/collection-traits-take-2/1272) (link is arbitrary first urlo result), but are blocked on at least GAT. What said traits would actually guarantee and how they'd be organized, however, is contentious. E.g. what performance suggestions do you put on what traits? But that's not this thread's discussion.

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [August 16, 2019, 7:29pm UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/13 "2019-08-16T19:29:42Z")

</div>

> [@CAD97](#):
>
> `[($key, $value),*].into_iter().collect()`

There's no true array iterator yet -- this is dereferencing into a slice and a `slice::Iter` by reference.

(or maybe it hits `IntoIterator for &[T; N]` for lengths up to 32, but that's still a `slice::Iter`.)

---

<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:** [August 16, 2019, 7:32pm UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/14 "2019-08-16T19:32:27Z")

</div>

Ah, whoops, missed the `&'a` when checking the docs. It could be constructed with a bunch of `.chain(once(($key, $val)))`, but that gives up the exact size knowledge unfortunately.

---

<div class="post-metadata">

**Author:** ![H2CO3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/h2co3/32/2849_2.png) [@H2CO3](https://internals.rust-lang.org/u/H2CO3)\
**Post date:** [August 16, 2019, 7:35pm UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/15 "2019-08-16T19:35:33Z")

</div>

Agreed, e.g. I absolutely love `BTreeMap` when implementing recursive structures that need to be `Hash` or `Ord`; you can't do that with a `HashMap` because of its very (randomized) nature.

@CAD97

> [@CAD97](#):
>
> Collection traits have been discussed [many times](https://internals.rust-lang.org/t/collection-traits-take-2/1272) (link is arbitrary first urlo result), but are blocked on at least GAT. What said traits would actually guarantee and how they'd be organized, however, is contentious.

Just one comment for this: it is completely true. I've been working a lot in Swift, which has collection traits in std. **They are a massive pain in the neck.** I feel that in an attempt to generalize over every possible use-case, the Swift collections library has been _massively overengineered_ in terms of traits. I literally didn't find a single good use case for them but they require so much wandering around the documentation (as they are implemented as ravioli code, with dozens of small traits organized into equally numerous levels of protocol conformance), it's very annoying, and I'm actually glad Rust doesn't have them.

(Meanwhile, usually I'm all for generic programming, and I actually don't find Swift's generic capabilities powerful enough, so I'm not the "you ain't need traits" guy on the block. It's just that collection traits are IMO very hard to get right, and not nearly as useful as one's intuition or inner good-practice-o-meter might say at first thought.)

---

<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:** [November 14, 2019, 7:39pm UTC](https://internals.rust-lang.org/t/should-hashmap-be-added-to-std-prelude/10717/16 "2019-11-14T19:39:04Z")

</div>

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