Literal hash-maps with duplicate keys?

19 views
Skip to first unread message

Brian Carper

unread,
May 29, 2009, 8:37:10 PM5/29/09
to Clojure
Can anyone explain this?

user> (def x {:foo :bar :foo :baz :foo :quux})
#'user/x
user> x
{:foo :bar, :foo :baz, :foo :quux}
user> (count (keys x))
3
user> (map x (keys x))
(:bar :bar :bar)

It's understandable that a literal map which includes the same key
twice with different values could return any one of the given values.
But I would expect the resulting map to have one key and one of the
values. Note:

user> (assoc {} :foo :bar :foo :baz :foo :quux)
{:foo :quux}
user> (conj {} [:foo :bar] [:foo :baz] [:foo :quux])
{:foo :quux}
user> (hash-map :foo :bar :foo :baz :foo :quux)
{:foo :quux}

Meikel Brandmeyer

unread,
May 30, 2009, 7:01:15 AM5/30/09
to clo...@googlegroups.com
Hi,

Am 30.05.2009 um 02:37 schrieb Brian Carper:

> Can anyone explain this?
>
> user> (def x {:foo :bar :foo :baz :foo :quux})
> #'user/x
> user> x
> {:foo :bar, :foo :baz, :foo :quux}
> user> (count (keys x))
> 3
> user> (map x (keys x))
> (:bar :bar :bar)

If I remember correctly, map literals smaller
than a certain size are based on array-map.
For speed reasons, this does not check for
duplicate keys. If you increase the size of
your literal beyond the threshold (was it
something around twenty entries?) the map
will be a hash-map and the effect should
go away...

My understanding is, that this falls under
"do broken stuff and you'll get broken stuff".
Map literals are most-likely small maps with
hard-wired keys. So the chance to have a
map like above is very small. And if there is
one I would strongly question the correctness.

So this shouldn't be a real problem in practice.

Sincerely
Meikel

Stephen C. Gilardi

unread,
May 30, 2009, 8:18:03 AM5/30/09
to clo...@googlegroups.com

On May 30, 2009, at 7:01 AM, Meikel Brandmeyer wrote:

> If I remember correctly, map literals smaller
> than a certain size are based on array-map.
> For speed reasons, this does not check for
> duplicate keys. If you increase the size of
> your literal beyond the threshold (was it
> something around twenty entries?) the map
> will be a hash-map and the effect should
> go away...

The threshold is currently 8, though that's an implementation detail,
not a promise.

user=> {:foo 1 :foo 2 :foo 3 :foo 4 :foo 5 :foo 6 :foo 7 :foo 8}
{:foo 1, :foo 2, :foo 3, :foo 4, :foo 5, :foo 6, :foo 7, :foo 8}
user=> {:foo 1 :foo 2 :foo 3 :foo 4 :foo 5 :foo 6 :foo 7 :foo 8 :foo 9}
{:foo 9}

> My understanding is, that this falls under
> "do broken stuff and you'll get broken stuff".
> Map literals are most-likely small maps with
> hard-wired keys. So the chance to have a
> map like above is very small. And if there is
> one I would strongly question the correctness.
>
> So this shouldn't be a real problem in practice.

+1

--Steve

Reply all
Reply to author
Forward
0 new messages