Skip to content
Browse files

Transient support for PersistentHashMap ported from Clojure

* New protocols:

  - IEditableCollection,
  - ITransientCollection,
  - ITransientAssociative.

* PersistentHashMap now implements IEditableCollection.

* TransientHashMap is the transient equivalent.

* cljs.core.PersistentHashMap/fromArrays now uses a transient map,

* ...as does cljs.core/hash-map.
  • Loading branch information...
1 parent 1211712 commit f3d8a0b78cd5be5d6ca57370e9b5d3b3f53f3b6e @michalmarczyk michalmarczyk committed with David Nolen Apr 20, 2012
Showing with 392 additions and 41 deletions.
  1. +392 −41 src/cljs/cljs/core.cljs
View
433 src/cljs/cljs/core.cljs
@@ -227,6 +227,17 @@
(-add-watch [this key f])
(-remove-watch [this key]))
+(defprotocol IEditableCollection
+ (-as-transient [coll]))
+
+(defprotocol ITransientCollection
+ (-conj! [tcoll val])
+ (-persistent! [tcoll]))
+
+(defprotocol ITransientAssociative
+ (-assoc! [tcoll key val])
+ (-dissoc! [tcoll key]))
+
;;;;;;;;;;;;;;;;;;; fundamentals ;;;;;;;;;;;;;;;
(defn ^boolean identical?
"Tests if 2 arguments are the same object"
@@ -2829,6 +2840,23 @@ reduces them without incurring seq initialization"
(recur (inc i) (assoc out (aget ks i) (aget vs i)))
out)))))
+;;; Transients
+
+(defn transient [coll]
+ (-as-transient coll))
+
+(defn persistent! [tcoll]
+ (-persistent! tcoll))
+
+(defn conj! [tcoll val]
+ (-conj! tcoll val))
+
+(defn assoc! [tcoll key val]
+ (-assoc! tcoll key val))
+
+(defn dissoc! [tcoll key]
+ (-dissoc! tcoll key))
+
;;; PersistentHashMap
(declare create-inode-seq create-array-node-seq reset! create-node atom deref)
@@ -2848,10 +2876,10 @@ reduces them without incurring seq initialization"
(defn- array-copy
([from i to j len]
(loop [i i j j len len]
- (when-not (zero? len)
- (aset to j (aget from i))
- (recur (inc i) (inc j) (dec len))))
- to))
+ (if (zero? len)
+ to
+ (do (aset to j (aget from i))
+ (recur (inc i) (inc j) (dec len)))))))
(defn- array-copy-downward
([from i to j len]
@@ -2873,9 +2901,20 @@ reduces them without incurring seq initialization"
(defn- bitpos [hash shift]
(bit-shift-left 1 (mask hash shift)))
+(defn- edit-and-set
+ ([inode edit i a]
+ (let [editable (.ensure-editable inode edit)]
+ (aset (.-arr editable) i a)
+ editable))
+ ([inode edit i a j b]
+ (let [editable (.ensure-editable inode edit)]
+ (aset (.-arr editable) i a)
+ (aset (.-arr editable) j b)
+ editable)))
+
(declare ArrayNode)
-(deftype BitmapIndexedNode [bitmap arr]
+(deftype BitmapIndexedNode [edit ^:mutable bitmap ^:mutable arr]
Object
(inode-assoc [inode shift hash key val added-leaf?]
(let [bit (bitpos hash shift)
@@ -2896,30 +2935,30 @@ reduces them without incurring seq initialization"
(+ shift 5) (cljs.core/hash (aget arr j)) (aget arr j) (aget arr (inc j)) added-leaf?)
(aget arr (inc j))))
(recur (inc i) (+ j 2))))))
- (ArrayNode. (inc n) nodes))
+ (ArrayNode. nil (inc n) nodes))
(let [new-arr (make-array (* 2 (inc n)))]
(array-copy arr 0 new-arr 0 (* 2 idx))
(aset new-arr (* 2 idx) key)
(aset added-leaf? 0 true)
(aset new-arr (inc (* 2 idx)) val)
(array-copy arr (* 2 idx) new-arr (* 2 (inc idx)) (* 2 (- n idx)))
- (BitmapIndexedNode. (bit-or bitmap bit) new-arr))))
+ (BitmapIndexedNode. nil (bit-or bitmap bit) new-arr))))
(let [key-or-nil (aget arr (* 2 idx))
val-or-node (aget arr (inc (* 2 idx)))]
(cond (coercive-= nil key-or-nil)
(let [n (.inode-assoc val-or-node (+ shift 5) hash key val added-leaf?)]
(if (identical? n val-or-node)
inode
- (BitmapIndexedNode. bitmap (clone-and-set arr (inc (* 2 idx)) n))))
+ (BitmapIndexedNode. nil bitmap (clone-and-set arr (inc (* 2 idx)) n))))
(= key key-or-nil)
(if (identical? val val-or-node)
inode
- (BitmapIndexedNode. bitmap (clone-and-set arr (inc (* 2 idx)) val)))
+ (BitmapIndexedNode. nil bitmap (clone-and-set arr (inc (* 2 idx)) val)))
:else
(do (aset added-leaf? 0 true)
- (BitmapIndexedNode. bitmap
+ (BitmapIndexedNode. nil bitmap
(clone-and-set arr (* 2 idx) nil (inc (* 2 idx))
(create-node (+ shift 5) key-or-nil val-or-node hash key val)))))))))
@@ -2933,11 +2972,11 @@ reduces them without incurring seq initialization"
(cond (coercive-= nil key-or-nil)
(let [n (.inode-without val-or-node (+ shift 5) hash key)]
(cond (identical? n val-or-node) inode
- (coercive-not= nil n) (BitmapIndexedNode. bitmap (clone-and-set arr (inc (* 2 idx)) n))
+ (coercive-not= nil n) (BitmapIndexedNode. nil bitmap (clone-and-set arr (inc (* 2 idx)) n))
(== bitmap bit) nil
- :else (BitmapIndexedNode. (bit-xor bitmap bit) (remove-pair arr idx))))
+ :else (BitmapIndexedNode. nil (bit-xor bitmap bit) (remove-pair arr idx))))
(= key key-or-nil)
- (BitmapIndexedNode. (bit-xor bitmap bit) (remove-pair arr idx))
+ (BitmapIndexedNode. nil (bit-xor bitmap bit) (remove-pair arr idx))
:else inode)))))
(inode-find [inode shift hash key]
@@ -2963,11 +3002,114 @@ reduces them without incurring seq initialization"
:else not-found)))))
(inode-seq [inode]
- (create-inode-seq arr)))
+ (create-inode-seq arr))
+
+ (ensure-editable [inode e]
+ (if (identical? e edit)
+ inode
+ (let [n (bit-count bitmap)
+ new-arr (make-array (if (neg? n) 4 (* 2 (inc n))))]
+ (array-copy arr 0 new-arr 0 (* 2 n))
+ (BitmapIndexedNode. e bitmap new-arr))))
+
+ (edit-and-remove-pair [inode e bit i]
+ (if (== bitmap bit)
+ nil
+ (let [editable (.ensure-editable inode e)
+ earr (.-arr editable)
+ len (.-length earr)]
+ (set! (.-bitmap editable) (bit-xor bit (.-bitmap editable)))
+ (array-copy earr (* 2 (inc i))
+ earr (* 2 i)
+ (- len (* 2 (inc i))))
+ (aset earr (- len 2) nil)
+ (aset earr (dec len) nil)
+ editable)))
+
+ (inode-assoc! [inode edit shift hash key val added-leaf?]
+ (let [bit (bitpos hash shift)
+ idx (bitmap-indexed-node-index bitmap bit)]
+ (if (zero? (bit-and bitmap bit))
+ (let [n (bit-count bitmap)]
+ (cond
+ (< (* 2 n) (.-length arr))
+ (let [editable (.ensure-editable inode edit)
+ earr (.-arr editable)]
+ (aset added-leaf? 0 true)
+ (array-copy-downward earr (* 2 idx)
+ earr (* 2 (inc idx))
+ (* 2 (- n idx)))
+ (aset earr (* 2 idx) key)
+ (aset earr (inc (* 2 idx)) val)
+ (set! (.-bitmap editable) (bit-or (.-bitmap editable) bit))
+ editable)
+
+ (>= n 16)
+ (let [nodes (make-array 32)
+ jdx (mask hash shift)]
+ (aset nodes jdx (.inode-assoc! cljs.core.BitmapIndexedNode/EMPTY edit (+ shift 5) hash key val added-leaf?))
+ (loop [i 0 j 0]
+ (if (< i 32)
+ (if (zero? (bit-and (bit-shift-right-zero-fill bitmap i) 1))
+ (recur (inc i) j)
+ (do (aset nodes i
+ (if (coercive-not= nil (aget arr j))
+ (.inode-assoc! cljs.core.BitmapIndexedNode/EMPTY
+ edit (+ shift 5) (cljs.core/hash (aget arr j)) (aget arr j) (aget arr (inc j)) added-leaf?)
+ (aget arr (inc j))))
+ (recur (inc i) (+ j 2))))))
+ (ArrayNode. edit (inc n) nodes))
+
+ :else
+ (let [new-arr (make-array (* 2 (+ n 4)))]
+ (array-copy arr 0 new-arr 0 (* 2 idx))
+ (aset new-arr (* 2 idx) key)
+ (aset added-leaf? 0 true)
+ (aset new-arr (inc (* 2 idx)) val)
+ (array-copy arr (* 2 idx) new-arr (* 2 (inc idx)) (* 2 (- n idx)))
+ (let [editable (.ensure-editable inode edit)]
+ (set! (.-arr editable) new-arr)
+ (set! (.-bitmap editable) (bit-or (.-bitmap editable) bit))
+ editable))))
+ (let [key-or-nil (aget arr (* 2 idx))
+ val-or-node (aget arr (inc (* 2 idx)))]
+ (cond (coercive-= nil key-or-nil)
+ (let [n (.inode-assoc! val-or-node edit (+ shift 5) hash key val added-leaf?)]
+ (if (identical? n val-or-node)
+ inode
+ (edit-and-set inode edit (inc (* 2 idx)) n)))
+
+ (= key key-or-nil)
+ (if (identical? val val-or-node)
+ inode
+ (edit-and-set inode edit (inc (* 2 idx)) val))
+
+ :else
+ (do (aset added-leaf? 0 true)
+ (edit-and-set inode edit (* 2 idx) nil (inc (* 2 idx))
+ (create-node edit (+ shift 5) key-or-nil val-or-node hash key val))))))))
+
+ (inode-without! [inode edit shift hash key removed-leaf?]
+ (let [bit (bitpos hash shift)]
+ (if (zero? (bit-and bitmap bit))
+ inode
+ (let [idx (bitmap-indexed-node-index bitmap bit)
+ key-or-nil (aget arr (* 2 idx))
+ val-or-node (aget arr (inc (* 2 idx)))]
+ (cond (coercive-= nil key-or-nil)
+ (let [n (.inode-without! val-or-node edit (+ shift 5) hash key removed-leaf?)]
+ (cond (identical? n val-or-node) inode
+ (coercive-not= nil n) (edit-and-set inode edit (inc (* 2 idx)) n)
+ (== bitmap bit) nil
+ :else (.edit-and-remove-pair inode edit bit idx)))
+ (= key key-or-nil)
+ (do (aset removed-leaf? 0 true)
+ (.edit-and-remove-pair inode edit bit idx))
+ :else inode))))))
-(set! cljs.core.BitmapIndexedNode/EMPTY (BitmapIndexedNode. 0 (make-array 0)))
+(set! cljs.core.BitmapIndexedNode/EMPTY (BitmapIndexedNode. nil 0 (make-array 0)))
-(defn- pack-array-node [array-node idx]
+(defn- pack-array-node [array-node edit idx]
(let [arr (.-arr array-node)
len (* 2 (dec (.-cnt array-node)))
new-arr (make-array len)]
@@ -2978,19 +3120,19 @@ reduces them without incurring seq initialization"
(do (aset new-arr j (aget arr i))
(recur (inc i) (+ j 2) (bit-or bitmap (bit-shift-left 1 i))))
(recur (inc i) j bitmap))
- (BitmapIndexedNode. bitmap new-arr)))))
+ (BitmapIndexedNode. edit bitmap new-arr)))))
-(deftype ArrayNode [cnt arr]
+(deftype ArrayNode [edit ^:mutable cnt ^:mutable arr]
Object
(inode-assoc [inode shift hash key val added-leaf?]
(let [idx (mask hash shift)
node (aget arr idx)]
(if (coercive-= nil node)
- (ArrayNode. (inc cnt) (clone-and-set arr idx (.inode-assoc cljs.core.BitmapIndexedNode/EMPTY (+ shift 5) hash key val added-leaf?)))
+ (ArrayNode. nil (inc cnt) (clone-and-set arr idx (.inode-assoc cljs.core.BitmapIndexedNode/EMPTY (+ shift 5) hash key val added-leaf?)))
(let [n (.inode-assoc node (+ shift 5) hash key val added-leaf?)]
(if (identical? n node)
inode
- (ArrayNode. cnt (clone-and-set arr idx n)))))))
+ (ArrayNode. nil cnt (clone-and-set arr idx n)))))))
(inode-without [inode shift hash key]
(let [idx (mask hash shift)
@@ -3004,10 +3146,10 @@ reduces them without incurring seq initialization"
(nil? n)
(if (<= cnt 8)
(pack-array-node inode idx)
- (ArrayNode. (dec cnt) (clone-and-set arr idx n)))
+ (ArrayNode. nil (dec cnt) (clone-and-set arr idx n)))
:else
- (ArrayNode. cnt (clone-and-set arr idx n))))
+ (ArrayNode. nil cnt (clone-and-set arr idx n))))
inode)))
(inode-find [inode shift hash key]
@@ -3025,7 +3167,44 @@ reduces them without incurring seq initialization"
not-found)))
(inode-seq [inode]
- (create-array-node-seq arr)))
+ (create-array-node-seq arr))
+
+ (ensure-editable [inode e]
+ (if (identical? e edit)
+ inode
+ (ArrayNode. e cnt (aclone arr))))
+
+ (inode-assoc! [inode edit shift hash key val added-leaf?]
+ (let [idx (mask hash shift)
+ node (aget arr idx)]
+ (if (coercive-= nil node)
+ (let [editable (edit-and-set inode edit idx (.inode-assoc! cljs.core.BitmapIndexedNode/EMPTY edit (+ shift 5) hash key val added-leaf?))]
+ (set! (.-cnt editable) (inc (.-cnt editable)))
+ editable)
+ (let [n (.inode-assoc! node edit (+ shift 5) hash key val added-leaf?)]
+ (if (identical? n node)
+ inode
+ (edit-and-set inode edit idx n))))))
+
+ (inode-without! [inode edit shift hash key removed-leaf?]
+ (let [idx (mask hash shift)
+ node (aget arr idx)]
+ (if (coercive-= nil node)
+ inode
+ (let [n (.inode-without! node edit (+ shift 5) hash key removed-leaf?)]
+ (cond
+ (identical? n node)
+ inode
+
+ (coercive-= nil n)
+ (if (<= cnt 8)
+ (pack-array-node inode edit idx)
+ (let [editable (edit-and-set inode edit idx n)]
+ (set! (.-cnt editable) (dec (.-cnt editable)))
+ editable))
+
+ :else
+ (edit-and-set inode edit idx n)))))))
(defn- hash-collision-node-find-index [arr cnt key]
(let [lim (* 2 cnt)]
@@ -3036,7 +3215,10 @@ reduces them without incurring seq initialization"
(recur (+ i 2)))
-1))))
-(deftype HashCollisionNode [__hash cnt arr]
+(deftype HashCollisionNode [edit
+ ^:mutable __hash
+ ^:mutable cnt
+ ^:mutable arr]
Object
(inode-assoc [inode shift hash key val added-leaf?]
(if (== hash __hash)
@@ -3048,18 +3230,18 @@ reduces them without incurring seq initialization"
(aset new-arr len key)
(aset new-arr (inc len) val)
(aset added-leaf? 0 true)
- (HashCollisionNode. __hash (inc cnt) new-arr))
+ (HashCollisionNode. nil __hash (inc cnt) new-arr))
(if (= (aget arr idx) val)
inode
- (HashCollisionNode. __hash cnt (clone-and-set arr (inc idx) val)))))
- (.inode-assoc (BitmapIndexedNode. (bitpos __hash shift) (array nil inode))
+ (HashCollisionNode. nil __hash cnt (clone-and-set arr (inc idx) val)))))
+ (.inode-assoc (BitmapIndexedNode. nil (bitpos __hash shift) (array nil inode))
shift hash key val added-leaf?)))
(inode-without [inode shift hash key]
(let [idx (hash-collision-node-find-index arr cnt key)]
(cond (== idx -1) inode
(== cnt 1) nil
- :else (HashCollisionNode. __hash (dec cnt) (remove-pair arr (quot idx 2))))))
+ :else (HashCollisionNode. nil __hash (dec cnt) (remove-pair arr (quot idx 2))))))
(inode-find [inode shift hash key]
(let [idx (hash-collision-node-find-index arr cnt key)]
@@ -3074,16 +3256,77 @@ reduces them without incurring seq initialization"
:else not-found)))
(inode-seq [inode]
- (create-inode-seq arr)))
+ (create-inode-seq arr))
+
+ (ensure-editable [inode e]
+ (if (identical? e edit)
+ inode
+ (let [new-arr (make-array (* 2 (inc cnt)))]
+ (array-copy arr 0 new-arr 0 (* 2 cnt))
+ (HashCollisionNode. e __hash cnt new-arr))))
+
+ (ensure-editable [inode e count array]
+ (if (identical? e edit)
+ (do (set! arr array)
+ (set! cnt count)
+ inode)
+ (HashCollisionNode. edit __hash count array)))
+
+ (inode-assoc! [inode edit shift hash key val added-leaf?]
+ (if (== hash __hash)
+ (let [idx (hash-collision-node-find-index arr cnt key)]
+ (if (== idx -1)
+ (if (> (.-length arr) (* 2 cnt))
+ (let [editable (edit-and-set inode edit (* 2 cnt) key (inc (* 2 cnt)) val)]
+ (aset added-leaf? 0 true)
+ (set! (.-cnt editable) (inc (.-cnt editable)))
+ editable)
+ (let [len (.-length arr)
+ new-arr (make-array (+ len 2))]
+ (array-copy arr 0 new-arr 0 len)
+ (aset new-arr len key)
+ (aset new-arr (inc len) val)
+ (aset added-leaf? 0 true)
+ (.ensure-editable inode edit (inc cnt) new-arr)))
+ (if (identical? (aget arr (inc idx)) val)
+ inode
+ (edit-and-set inode edit (inc idx) val))))
+ (.inode-assoc! (BitmapIndexedNode. edit (bitpos __hash shift) (array nil inode nil nil))
+ edit shift hash key val added-leaf?)))
-(defn- create-node [shift key1 val1 key2hash key2 val2]
- (let [key1hash (hash key1)]
- (if (== key1hash key2hash)
- (HashCollisionNode. key1hash 2 (array key1 val1 key2 val2))
- (let [added-leaf? (array false)]
- (-> cljs.core.BitmapIndexedNode/EMPTY
- (.inode-assoc shift key1hash key1 val1 added-leaf?)
- (.inode-assoc shift key2hash key2 val2 added-leaf?))))))
+ (inode-without! [inode edit shift hash key removed-leaf?]
+ (let [idx (hash-collision-node-find-index arr cnt key)]
+ (if (== idx -1)
+ inode
+ (do (aset removed-leaf? 0 true)
+ (if (== cnt 1)
+ nil
+ (let [editable (.ensure-editable inode edit)
+ earr (.-arr editable)]
+ (aset earr idx (aget earr (- (* 2 cnt) 2)))
+ (aset earr (inc idx) (aget earr (dec (* 2 cnt))))
+ (aset earr (dec (* 2 cnt)) nil)
+ (aset earr (- (* 2 cnt) 2) nil)
+ (set! (.-cnt editable) (dec (.-cnt editable)))
+ editable)))))))
+
+(defn- create-node
+ ([shift key1 val1 key2hash key2 val2]
+ (let [key1hash (hash key1)]
+ (if (== key1hash key2hash)
+ (HashCollisionNode. nil key1hash 2 (array key1 val1 key2 val2))
+ (let [added-leaf? (array false)]
+ (-> cljs.core.BitmapIndexedNode/EMPTY
+ (.inode-assoc shift key1hash key1 val1 added-leaf?)
+ (.inode-assoc shift key2hash key2 val2 added-leaf?))))))
+ ([edit shift key1 val1 key2hash key2 val2]
+ (let [key1hash (hash key1)]
+ (if (== key1hash key2hash)
+ (HashCollisionNode. nil key1hash 2 (array key1 val1 key2 val2))
+ (let [added-leaf? (array false)]
+ (-> cljs.core.BitmapIndexedNode/EMPTY
+ (.inode-assoc! edit shift key1hash key1 val1 added-leaf?)
+ (.inode-assoc! edit shift key2hash key2 val2 added-leaf?)))))))
(deftype NodeSeq [meta nodes i s]
IMeta
@@ -3159,6 +3402,8 @@ reduces them without incurring seq initialization"
(recur (inc j))))))
(ArrayNodeSeq. meta nodes i s))))
+(declare TransientHashMap)
+
(deftype PersistentHashMap [meta cnt root has-nil? nil-val]
Object
(toString [this]
@@ -3245,17 +3490,123 @@ reduces them without incurring seq initialization"
(-lookup coll k))
(-invoke [coll k not-found]
- (-lookup coll k not-found)))
+ (-lookup coll k not-found))
+
+ IEditableCollection
+ (-as-transient [coll]
+ (TransientHashMap. (js-obj) root cnt has-nil? nil-val)))
(set! cljs.core.PersistentHashMap/EMPTY (PersistentHashMap. nil 0 nil false nil))
(set! cljs.core.PersistentHashMap/fromArrays
(fn [ks vs]
(let [len (.-length ks)]
- (loop [i 0 out cljs.core.PersistentHashMap/EMPTY]
+ (loop [i 0 out (transient cljs.core.PersistentHashMap/EMPTY)]
(if (< i len)
- (recur (inc i) (assoc out (aget ks i) (aget vs i)))
- out)))))
+ (recur (inc i) (assoc! out (aget ks i) (aget vs i)))
+ (persistent! out))))))
+
+(deftype TransientHashMap [^:mutable edit
+ ^:mutable root
+ ^:mutable count
+ ^:mutable has-nil?
+ ^:mutable nil-val]
+ Object
+ (conj! [tcoll o]
+ (if edit
+ (if (satisfies? IMapEntry o)
+ (.assoc! tcoll (key o) (val o))
+ (loop [es (seq o) tcoll tcoll]
+ (if-let [e (first es)]
+ (recur (next es)
+ (.assoc! tcoll (key e) (val e)))
+ tcoll)))
+ (throw (js/Error. "conj! after persistent"))))
+
+ (assoc! [tcoll k v]
+ (if edit
+ (if (nil? k)
+ (do (if (identical? nil-val v)
+ nil
+ (set! nil-val v))
+ (if has-nil?
+ nil
+ (do (set! count (inc count))
+ (set! has-nil? true)))
+ tcoll)
+ (let [added-leaf? (array false)
+ node (-> (if (nil? root)
+ cljs.core.BitmapIndexedNode/EMPTY
+ root)
+ (.inode-assoc! edit 0 (hash k) k v added-leaf?))]
+ (if (identical? node root)
+ nil
+ (set! root node))
+ (if (aget added-leaf? 0)
+ (set! count (inc count)))
+ tcoll))
+ (throw (js/Error. "assoc! after persistent!"))))
+
+ (without! [tcoll k]
+ (if edit
+ (if (nil? k)
+ (if has-nil?
+ (do (set! has-nil? false)
+ (set! nil-val nil)
+ (set! count (dec count))
+ tcoll)
+ tcoll)
+ (if (nil? root)
+ tcoll
+ (let [removed-leaf? (array false)
+ node (.inode-without! root edit 0 (hash k) k removed-leaf?)]
+ (if (identical? node root)
+ nil
+ (set! root node))
+ (if (aget removed-leaf? 0)
+ (set! count (dec count)))
+ tcoll)))
+ (throw (js/Error. "dissoc! after persistent!"))))
+
+ (persistent! [tcoll]
+ (if edit
+ (do (set! edit nil)
+ (PersistentHashMap. nil count root has-nil? nil-val))
+ (throw (js/Error. "persistent! called twice"))))
+
+ ICounted
+ (-count [coll]
+ (if edit
+ count
+ (throw (js/Error. "count after persistent!"))))
+
+ ILookup
+ (-lookup [tcoll k]
+ (if (nil? k)
+ (if has-nil?
+ nil-val)
+ (if (nil? root)
+ nil
+ (nth (.inode-find root 0 (hash k) k) 1))))
+
+ (-lookup [tcoll k not-found]
+ (if (nil? k)
+ (if has-nil?
+ nil-val
+ not-found)
+ (if (nil? root)
+ not-found
+ (nth (.inode-find root 0 (hash k) k not-found) 1))))
+
+ ITransientCollection
+ (-conj! [tcoll val] (.conj! tcoll val))
+
+ (-persistent! [tcoll] (.persistent! tcoll))
+
+ ITransientAssociative
+ (-assoc! [tcoll key val] (.assoc! tcoll key val))
+
+ (-dissoc! [tcoll key] (.without! tcoll key)))
(defn hash-map
"keyval => key val

0 comments on commit f3d8a0b

Please sign in to comment.
Something went wrong with that request. Please try again.