Commits

Meikel Brandmeyer committed 414fd04

Move LazyMap implementation to a deftype instead of reify

  • Participants
  • Parent commits 35d2502
  • Branches new

Comments (0)

Files changed (1)

File src/main/clojure/de/kotka/lazymap.clj

   lazy-hash-map, lazy-sorted-map, lazy-struct-map, lazy-struct, lazy-assoc
   and their * counterpart functions."
   (:import
-     clojure.lang.IObj
-     clojure.lang.IFn
-     clojure.lang.IMapEntry
-     clojure.lang.IPersistentVector
-     clojure.lang.ISeq
-     clojure.lang.SeqIterator))
+    clojure.lang.IObj
+    clojure.lang.IFn
+    clojure.lang.ILookup
+    clojure.lang.IMapEntry
+    clojure.lang.IPersistentMap
+    clojure.lang.IPersistentVector
+    clojure.lang.ISeq
+    clojure.lang.Seqable
+    clojure.lang.SeqIterator))
 
 (defprotocol ILazyMapEntry
   "ILazyMapEntry describes the behaviour of a lazy MapEntry. It provides
      (empty [this]   ())
      (seq   [this]   this))))
 
+(declare create-lazy-map)
+
+(deftype LazyPersistentMap
+  [base metadata]
+  ILazyPersistentMap
+  (delay-assoc [this k v] (create-lazy-map (assoc base k v) metadata))
+  IPersistentMap
+  (assoc       [this k v] (create-lazy-map (assoc base k (delay v)) metadata))
+  (assocEx
+    [this k v]
+    (when (.containsKey base k)
+      (throw (Exception. (str "Key already present in map: " k))))
+    (.assoc this k v))
+  (without     [this k] (create-lazy-map (dissoc base k) metadata))
+  ; Associative
+  (containsKey [this k] (contains? base k))
+  (entryAt     [this k] (LazyMapEntry. k (base k)))
+  ; IPersistentCollection
+  (count       [this]   (count base))
+  (cons
+    [this o]
+    (if (satisfies? ILazyMapEntry o)
+      (delay-assoc this (get-key o) (get-raw-value o))
+      (into this o)))
+  (empty [this]   (create-lazy-map (empty base) nil))
+  ILookup
+  (valAt [this k] (.valAt this k nil))
+  (valAt
+    [this k not-found]
+    (if (contains? base k)
+      (-> base (get k) force)
+      not-found))
+  IFn
+  (invoke [this k]           (.valAt this k nil))
+  (invoke [this k not-found] (.valAt this k not-found))
+  (applyTo
+    [this args]
+    (let [[k v & rest-args :as args] (seq args)]
+      (when (or (not args) rest-args)
+        (throw (Exception. "lazy map must be called with one or two arguments")))
+      (.valAt this k v)))
+  Seqable
+  (seq
+    [this]
+    (when-let [inner-seq (seq base)]
+      (create-lazy-map-seq inner-seq)))
+  IObj
+  (withMeta [this new-metadata] (create-lazy-map base new-metadata))
+  ; IMeta
+  (meta     [this] metadata)
+  Iterable
+  (iterator [this] (-> this .seq SeqIterator.)))
+
 (defn create-lazy-map
   ([base]
    (create-lazy-map base nil))
   ([base metadata]
-   (reify [ILazyMap IFn IObj]
-     ; ILazyMap
-     (lazyAssoc [this k v] (create-lazy-map (assoc base k v) metadata))
-     ; IPersistentMap
-     (assoc     [this k v] (create-lazy-map (assoc base k (delay v)) metadata))
-     (assocEx
-       [this k v]
-       (when (.containsKey base k)
-         (throw (Exception. (str "Key already present in map: " k))))
-       (.assoc this k v))
-     (without     [this k] (create-lazy-map (dissoc base k) metadata))
-     ; Associative
-     (containsKey [this k] (contains? base k))
-     (entryAt     [this k] (LazyMapEntry. k (base k)))
-     ; IPersistentCollection
-     (count       [this]   (count base))
-     (cons
-       [this o]
-       (if (satisfies? ILazyMapEntry o)
-         (.lazyAssoc this (get-key o) (get-raw-value o))
-         (reduce #(.cons #^ILazyMap %1 %2) this o)))
-     (empty [this]   (create-lazy-map (empty base) nil))
-     ; ILookup
-     (valAt [this k] (.valAt this k nil))
-     (valAt
-       [this k not-found]
-       (if (contains? base k)
-         (-> base (get k) force)
-         not-found))
-     ; IFn
-     (invoke [this k]           (.valAt this k nil))
-     (invoke [this k not-found] (.valAt this k not-found))
-     (applyTo
-       [this args]
-       (let [[k v & rest-args :as args] (seq args)]
-         (when (or (not args) rest-args)
-           (throw (Exception. "lazy map must be called with one or two arguments")))
-         (.valAt this k v)))
-     ; Seqable
-     (seq
-       [this]
-       (when-let [inner-seq (seq base)]
-         (create-lazy-map-seq inner-seq)))
-     ; IObj
-     (withMeta [this new-metadata] (create-lazy-map base new-metadata))
-     ; IMeta
-     (meta     [this] metadata)
-     ; Iterable
-     (iterator [this] (-> this .seq SeqIterator.)))))
+   (LazyPersistentMap. base metadata)))
 
 (defn- quote-values
   [kvs]