Welcome! Please see the About page for a little more info on how this works.

+3 votes
in Docs by
edited by

The docstring of hash-map states that it returns a hash map.
However, there's an arity with no arguments that returns an empty array map.

So there's a discrepancy between the docs and the impl.

1 Answer

0 votes

The point of confusion here is that "persistent hash map" is the abstraction here, but there are two concrete implementations: hash-map (PersistentHashMap) and array-map (PersistentArrayMap), and the latter changes type to the former based on map size.

hash-map is a constructor for the abstraction of persistent hash maps (generic), and makes no promises about the returned concrete type. However array-map IS (explicitly) a constructor for array-maps. There is no constructor function explicitly for PersistentHashMap.

I would understand if you said that the abstraction here is "persistent map". But not so much with "persistent hash map".

What exactly makes an array map an implementation of a hash map? I couldn't find any mentions of it anywhere (and the reference does mention array maps explicitly as a separate thing), and the impl doesn't use hashes at all, expectedly so. And conceptually, nothing about an array map makes it related to hash maps except for the fact that both are maps.

Even if I avoid inspecting the results of `(type ...)` called on any such maps, there is still an expectation tied to the words "hash map" - that the `hash` function will be used. One might argue that it's not important at all, and I agree that it's true for almost all cases, but it's definitely confusing when debugging anything related to hashes and maps.

What makes it even more confusing is that, while it feels like pretty much a common knowledge at this point that a map literal with more than 8 items is a hash map, `(hash-map 1 2)` will return a hash map, not an array map.

And there are other distinctions. At the very least, `print-dup` is defined for `PersistentHashMap`, but not for `PersistentArrayMap`, leading to unexpected things like `#=(clojure.lang.PersistentArrayMap/create {})`.
Ok, "persistent maps" is fairer, the important type is IPersistentMap.

How are you getting to the last example? `pr` or `print` aren't going to give you that.
With `(binding [*print-dup* true] (prn {}))`.