On Sun, Oct 11, 2009 at 8:55 PM, Angel Java Lopez <ajlopez2...@gmail.com>wrote:

> Hi people!
>
> I just discovered that maps support duplicated keys:
>
> user=> {:a 1 :b 2 :a 3}
> {:a 1, :b 2, :a 3}
>
> It was not clear to me, from documentation. I presumed that maps are like
> dictionaries.
>
> What is the rationale behind this behaviour?
>

I doubt there is one. I suspect it's a bug.

=> (assoc {:a 1 :b 2} :a 3)
{:a 3, :b 2}

=> (type {:a 1 :b 2 :a 3})
clojure.lang.PersistentArrayMap

=> (type (assoc {:a 1 :b 2} :a 3))
clojure.lang.PersistentArrayMap

Looks like there's a constructor that breaks the PersistentArrayMap (and
Map) contract and is used when building one from a literal. Associng the
key-value pairs one by one into an empty map is probably the only way to fix
it. Detecting duplicate keys in map literals at read time is NOT enough:

=>(def x :a)
=> (def y :b)
=> (def z :c)
=> {x 1 y 2 z 3}
{:a 1, :b 2, :c 3}
=> (def z :a)
=> {x 1 y 2 z 3}
{:a 1, :b 2, :a 3}

Runtime-variable keys can be duplicates without it being evident at read
time, or even predictable at all (equivalent to the halting problem). There
are only two behaviors that seem reasonable here, duplicate keys produce a
runtime exception or duplicate keys quietly overwrite earlier ones. The
latter is achieved by the "an array literal is a shorthand for (assoc (assoc
(assoc ... (assoc {} k1 v1) ... k2 v2) k3 v3) k4 v4)" semantics, whether
implemented that way or in some more-efficient way (transients? special
constructor?) and both have situations where they might be desirable. I'd
argue for the former, it throws an exception, on the basis that explicit
associng (or (reduce conj {} [[k1 v1] [k2 v2] [k3 v3]]) or (hash-map k1 v1
k2 v2 k3 v3)) can be used to achieve the latter effect where desired, and
most usually duplicate keys would represent an error. Duplicate keys
detected at read time (same keyword, quoted symbol/form, string or numeric
literal, or var) could of course be reported as errors at the compilation
stage.

=> (reduce conj {} [[:a 1] [:b 2] [:c 3]])
{:c 3, :b 2, :a 1}
=> (reduce conj {} [[:a 1] [:b 2] [:a 3]])
{:b 2, :a 3}
=> (reduce conj {} [[x 1] [y 2] [z 3]])
{:b 2, :a 3}
=> (hash-map x 1 y 2 z 3)
{:a 3, :b 2}

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to