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 -~----------~----~----~----~------~----~------~--~---