From 78064db9bd8c44941cb28eb5003ce5ea2708a619 Mon Sep 17 00:00:00 2001 From: Alex Redington Date: Fri, 17 Feb 2012 15:48:50 -0800 Subject: [PATCH 1/2] Refactor of some of the clojure .java code to fix CLJ-700. --- src/jvm/clojure/lang/Associative.java | 5 +---- src/jvm/clojure/lang/IAssociative.java | 21 +++++++++++++++++++++ src/jvm/clojure/lang/IPersistentSet.java | 6 ++---- src/jvm/clojure/lang/ISet.java | 17 +++++++++++++++++ src/jvm/clojure/lang/ITransientAssociative.java | 3 ++- src/jvm/clojure/lang/ITransientSet.java | 4 +--- src/jvm/clojure/lang/PersistentArrayMap.java | 11 +++++++++++ src/jvm/clojure/lang/PersistentHashMap.java | 12 ++++++++++++ src/jvm/clojure/lang/PersistentVector.java | 17 +++++++++++++++++ src/jvm/clojure/lang/RT.java | 16 ++++++++-------- test/clojure/test_clojure/transients.clj | 13 +++++++++++++ 11 files changed, 105 insertions(+), 20 deletions(-) create mode 100644 src/jvm/clojure/lang/IAssociative.java create mode 100644 src/jvm/clojure/lang/ISet.java diff --git a/src/jvm/clojure/lang/Associative.java b/src/jvm/clojure/lang/Associative.java index a239994..35474f5 100644 --- a/src/jvm/clojure/lang/Associative.java +++ b/src/jvm/clojure/lang/Associative.java @@ -9,10 +9,7 @@ package clojure.lang; * the terms of this license. * You must not remove this notice, or any other, from this software. */ -public interface Associative extends IPersistentCollection, ILookup{ -boolean containsKey(Object key); - -IMapEntry entryAt(Object key); +public interface Associative extends IPersistentCollection, IAssociative{ Associative assoc(Object key, Object val); diff --git a/src/jvm/clojure/lang/IAssociative.java b/src/jvm/clojure/lang/IAssociative.java new file mode 100644 index 0000000..b65c278 --- /dev/null +++ b/src/jvm/clojure/lang/IAssociative.java @@ -0,0 +1,21 @@ +package clojure.lang; + +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + */ + +public interface IAssociative extends ILookup { + + boolean containsKey(Object key); + + IMapEntry entryAt(Object key); + + IAssociative assoc(Object key, Object val); + +} diff --git a/src/jvm/clojure/lang/IPersistentSet.java b/src/jvm/clojure/lang/IPersistentSet.java index 144d15a..3fce1ae 100644 --- a/src/jvm/clojure/lang/IPersistentSet.java +++ b/src/jvm/clojure/lang/IPersistentSet.java @@ -12,8 +12,6 @@ package clojure.lang; -public interface IPersistentSet extends IPersistentCollection, Counted{ - public IPersistentSet disjoin(Object key) ; - public boolean contains(Object key); - public Object get(Object key); +public interface IPersistentSet extends IPersistentCollection, ISet, Counted{ + public IPersistentSet disjoin(Object key) ; } diff --git a/src/jvm/clojure/lang/ISet.java b/src/jvm/clojure/lang/ISet.java new file mode 100644 index 0000000..9a8a8ce --- /dev/null +++ b/src/jvm/clojure/lang/ISet.java @@ -0,0 +1,17 @@ +package clojure.lang; + +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + */ + +public interface ISet extends Counted { + public boolean contains(Object key); + public Object get(Object key); + public ISet disjoin(Object key); +} diff --git a/src/jvm/clojure/lang/ITransientAssociative.java b/src/jvm/clojure/lang/ITransientAssociative.java index a4d2655..b7b68bf 100644 --- a/src/jvm/clojure/lang/ITransientAssociative.java +++ b/src/jvm/clojure/lang/ITransientAssociative.java @@ -12,7 +12,8 @@ package clojure.lang; -public interface ITransientAssociative extends ITransientCollection, ILookup{ +public interface ITransientAssociative extends ITransientCollection, IAssociative { ITransientAssociative assoc(Object key, Object val); + } diff --git a/src/jvm/clojure/lang/ITransientSet.java b/src/jvm/clojure/lang/ITransientSet.java index 7d1ec51..348dd97 100644 --- a/src/jvm/clojure/lang/ITransientSet.java +++ b/src/jvm/clojure/lang/ITransientSet.java @@ -12,8 +12,6 @@ package clojure.lang; -public interface ITransientSet extends ITransientCollection, Counted{ +public interface ITransientSet extends ITransientCollection, ISet, Counted{ public ITransientSet disjoin(Object key) ; - public boolean contains(Object key); - public Object get(Object key); } diff --git a/src/jvm/clojure/lang/PersistentArrayMap.java b/src/jvm/clojure/lang/PersistentArrayMap.java index 541f4e2..77eff7a 100644 --- a/src/jvm/clojure/lang/PersistentArrayMap.java +++ b/src/jvm/clojure/lang/PersistentArrayMap.java @@ -304,6 +304,17 @@ static final class TransientArrayMap extends ATransientMap { this.len = array.length; } + public boolean containsKey(Object key){ + return indexOf(key) >= 0; + } + + public IMapEntry entryAt(Object key){ + int i = indexOf(key); + if(i >= 0) + return new MapEntry(array[i],array[i+1]); + return null; + } + private int indexOf(Object key){ for(int i = 0; i < len; i += 2) { diff --git a/src/jvm/clojure/lang/PersistentHashMap.java b/src/jvm/clojure/lang/PersistentHashMap.java index c36b159..83e140f 100644 --- a/src/jvm/clojure/lang/PersistentHashMap.java +++ b/src/jvm/clojure/lang/PersistentHashMap.java @@ -254,6 +254,18 @@ static final class TransientHashMap extends ATransientMap { this.nullValue = nullValue; } + public boolean containsKey(Object key){ + if(key == null) + return hasNull; + return (root != null) ? root.find(0, Util.hash(key), key, NOT_FOUND) != NOT_FOUND : false; + } + + public IMapEntry entryAt(Object key){ + if(key == null) + return hasNull ? new MapEntry(null, nullValue) : null; + return (root != null) ? root.find(0, Util.hash(key), key) : null; + } + ITransientMap doAssoc(Object key, Object val) { if (key == null) { if (this.nullValue != val) diff --git a/src/jvm/clojure/lang/PersistentVector.java b/src/jvm/clojure/lang/PersistentVector.java index eb56d0f..5294fec 100644 --- a/src/jvm/clojure/lang/PersistentVector.java +++ b/src/jvm/clojure/lang/PersistentVector.java @@ -440,6 +440,23 @@ static final class TransientVector extends AFn implements ITransientVector, Coun this(v.cnt, v.shift, editableRoot(v.root), editableTail(v.tail)); } + public boolean containsKey(Object key){ + if(!(Util.isInteger(key))) + return false; + int i = ((Number) key).intValue(); + return i >= 0 && i < count(); + } + + public IMapEntry entryAt(Object key){ + if(Util.isInteger(key)) + { + int i = ((Number) key).intValue(); + if(i >= 0 && i < count()) + return new MapEntry(key, nth(i)); + } + return null; + } + public int count(){ ensureEditable(); return cnt; diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index 6595fc6..922d3a1 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -642,8 +642,8 @@ static Object getFrom(Object coll, Object key){ Map m = (Map) coll; return m.get(key); } - else if(coll instanceof IPersistentSet) { - IPersistentSet set = (IPersistentSet) coll; + else if(coll instanceof ISet) { + ISet set = (ISet) coll; return set.get(key); } else if(key instanceof Number && (coll instanceof String || coll.getClass().isArray())) { @@ -671,8 +671,8 @@ static Object getFrom(Object coll, Object key, Object notFound){ return m.get(key); return notFound; } - else if(coll instanceof IPersistentSet) { - IPersistentSet set = (IPersistentSet) coll; + else if(coll instanceof ISet) { + ISet set = (ISet) coll; if(set.contains(key)) return set.get(key); return notFound; @@ -694,10 +694,10 @@ static public Associative assoc(Object coll, Object key, Object val){ static public Object contains(Object coll, Object key){ if(coll == null) return F; - else if(coll instanceof Associative) - return ((Associative) coll).containsKey(key) ? T : F; - else if(coll instanceof IPersistentSet) - return ((IPersistentSet) coll).contains(key) ? T : F; + else if(coll instanceof IAssociative) + return ((IAssociative) coll).containsKey(key) ? T : F; + else if(coll instanceof ISet) + return ((ISet) coll).contains(key) ? T : F; else if(coll instanceof Map) { Map m = (Map) coll; return m.containsKey(key) ? T : F; diff --git a/test/clojure/test_clojure/transients.clj b/test/clojure/test_clojure/transients.clj index 2a88bdd..7bf912e 100644 --- a/test/clojure/test_clojure/transients.clj +++ b/test/clojure/test_clojure/transients.clj @@ -31,3 +31,16 @@ (deftest empty-transient (is (= false (.contains (transient #{}) :bogus-key)))) + +(deftest contains-on-transients + (are [x y] (contains? (transient x) y) + {:x "y"} :x + (hash-map :x "y") :x + [1 2 3] 0 + #{:x} :x)) + +(deftest keyword-access-on-transient-sets + (is (= (:x (transient #{:x})) :x))) + +(deftest get-access-on-transient-sets + (is (= (get (transient #{:x}) :x) :x))) -- 1.7.10 From 815f5cc5080ee13506afd74388f2d0e72baab356 Mon Sep 17 00:00:00 2001 From: Stuart Halloway Date: Fri, 8 Jun 2012 13:39:41 -0400 Subject: [PATCH 2/2] more CLJ-700: refresh to use hasheq --- src/jvm/clojure/lang/PersistentHashMap.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jvm/clojure/lang/PersistentHashMap.java b/src/jvm/clojure/lang/PersistentHashMap.java index 83e140f..1078364 100644 --- a/src/jvm/clojure/lang/PersistentHashMap.java +++ b/src/jvm/clojure/lang/PersistentHashMap.java @@ -257,13 +257,13 @@ static final class TransientHashMap extends ATransientMap { public boolean containsKey(Object key){ if(key == null) return hasNull; - return (root != null) ? root.find(0, Util.hash(key), key, NOT_FOUND) != NOT_FOUND : false; + return (root != null) ? root.find(0, hash(key), key, NOT_FOUND) != NOT_FOUND : false; } public IMapEntry entryAt(Object key){ if(key == null) return hasNull ? new MapEntry(null, nullValue) : null; - return (root != null) ? root.find(0, Util.hash(key), key) : null; + return (root != null) ? root.find(0, hash(key), key) : null; } ITransientMap doAssoc(Object key, Object val) { -- 1.7.10