diff options
-rw-r--r-- | src/clj/clojure/core.clj | 12 | ||||
-rw-r--r-- | src/jvm/clojure/lang/PersistentArrayMap.java | 11 | ||||
-rw-r--r-- | src/jvm/clojure/lang/PersistentHashMap.java | 25 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 4 |
4 files changed, 37 insertions, 15 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index b4d4a31e..b5909407 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -283,7 +283,7 @@ Returns a new hash map with supplied mappings." ([] {}) ([& keyvals] - (. clojure.lang.PersistentHashMap (create keyvals)))) + (. clojure.lang.PersistentHashMap (createWithCheck keyvals)))) (defn hash-set "Returns a new hash set with supplied keys." @@ -2971,7 +2971,7 @@ (defn array-map "Constructs an array-map." ([] (. clojure.lang.PersistentArrayMap EMPTY)) - ([& keyvals] (new clojure.lang.PersistentArrayMap (to-array keyvals)))) + ([& keyvals] (clojure.lang.PersistentArrayMap/createWithCheck (to-array keyvals)))) (defn nthnext "Returns the nth next of coll, (seq coll) when n is 0." @@ -2984,7 +2984,7 @@ ;redefine let and loop with destructuring (defn destructure [bindings] - (let [bmap (apply array-map bindings) + (let [bents (partition 2 bindings) pb (fn pb [bvec b v] (let [pvec (fn [bvec b val] @@ -3035,10 +3035,10 @@ (vector? b) (pvec bvec b v) (map? b) (pmap bvec b v) :else (throw (new Exception (str "Unsupported binding form: " b)))))) - process-entry (fn [bvec b] (pb bvec (key b) (val b)))] - (if (every? symbol? (keys bmap)) + process-entry (fn [bvec b] (pb bvec (first b) (second b)))] + (if (every? symbol? (map first bents)) bindings - (reduce process-entry [] bmap)))) + (reduce process-entry [] bents)))) (defmacro let "Evaluates the exprs in a lexical context in which the symbols in diff --git a/src/jvm/clojure/lang/PersistentArrayMap.java b/src/jvm/clojure/lang/PersistentArrayMap.java index 8f63e5f8..7965c92e 100644 --- a/src/jvm/clojure/lang/PersistentArrayMap.java +++ b/src/jvm/clojure/lang/PersistentArrayMap.java @@ -60,6 +60,17 @@ IPersistentMap createHT(Object[] init){ return PersistentHashMap.create(meta(), init); } +static public PersistentArrayMap createWithCheck(Object[] init){ + for(int i=0;i< init.length;i += 2) + { + for(int j=i+2;j<init.length;j += 2) + { + if(equalKey(init[i],init[j])) + throw new IllegalArgumentException("Duplicate key: " + init[i]); + } + } + return new PersistentArrayMap(init); +} /** * This ctor captures/aliases the passed array, so do not modify later * diff --git a/src/jvm/clojure/lang/PersistentHashMap.java b/src/jvm/clojure/lang/PersistentHashMap.java index 4fae3f30..6f956a7f 100644 --- a/src/jvm/clojure/lang/PersistentHashMap.java +++ b/src/jvm/clojure/lang/PersistentHashMap.java @@ -58,15 +58,13 @@ public static PersistentHashMap create(Object... init){ return (PersistentHashMap) ret.persistent(); } -public static PersistentHashMap create(List init){ +public static PersistentHashMap createWithCheck(Object... init){ ITransientMap ret = EMPTY.asTransient(); - for(Iterator i = init.iterator(); i.hasNext();) + for(int i = 0; i < init.length; i += 2) { - Object key = i.next(); - if(!i.hasNext()) - throw new IllegalArgumentException(String.format("No value supplied for key: %s", key)); - Object val = i.next(); - ret = ret.assoc(key, val); + ret = ret.assoc(init[i], init[i + 1]); + if(ret.count() != i/2 + 1) + throw new IllegalArgumentException("Duplicate key: " + init[i]); } return (PersistentHashMap) ret.persistent(); } @@ -82,6 +80,19 @@ static public PersistentHashMap create(ISeq items){ return (PersistentHashMap) ret.persistent(); } +static public PersistentHashMap createWithCheck(ISeq items){ + ITransientMap ret = EMPTY.asTransient(); + for(int i=0; items != null; items = items.next().next(), ++i) + { + if(items.next() == null) + throw new IllegalArgumentException(String.format("No value supplied for key: %s", items.first())); + ret = ret.assoc(items.first(), RT.second(items)); + if(ret.count() != i + 1) + throw new IllegalArgumentException("Duplicate key: " + items.first()); + } + return (PersistentHashMap) ret.persistent(); +} + /* * @param init {key1,val1,key2,val2,...} */ diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index 22b57cf7..13afd8fd 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -1018,8 +1018,8 @@ static public IPersistentMap map(Object... init){ if(init == null) return PersistentArrayMap.EMPTY; else if(init.length <= PersistentArrayMap.HASHTABLE_THRESHOLD) - return new PersistentArrayMap(init); - return PersistentHashMap.create(init); + return PersistentArrayMap.createWithCheck(init); + return PersistentHashMap.createWithCheck(init); } static public IPersistentSet set(Object... init){ |