Meikel  Brandmeyer avatar Meikel Brandmeyer committed bae6857

Moved ILazyMapEntry to deftype and protocols

Comments (0)

Files changed (1)

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

      clojure.lang.ISeq
      clojure.lang.SeqIterator))
 
-(gen-interface
-  :name    de.kotka.lazymap.ILazyMapEntry
-  :extends [clojure.lang.IMapEntry]
-  :methods [[getRawValue [] clojure.lang.Delay]])
+(defprotocol ILazyMapEntry
+  "ILazyMapEntry describes the behaviour of a lazy MapEntry. It provides
+  an additional method (over IMapEntry), which returns the raw delay object
+  and not the forced value."
+  (get-key       [lazy-map-entry] "Return the key of the map entry.")
+  (get-raw-value [lazy-map-entry] "Return the underlying delay object."))
+
+; Extend the IMapEntry interface to act also like ILazyMapEntry.
+; For a IMapEntry get-raw-value just returns the given value as
+; wrapped in a delay. Similar a vector of two elements might be
+; used in place of a IMapEntry.
+(extend-protocol ILazyMapEntry
+  IMapEntry
+  (get-key       [#^IMapEntry this] (.getKey this))
+  (get-raw-value [#^IMapEntry this] (let [v (.getValue this)] (delay v)))
+  IPersistentVector
+  (get-key [this] (this 0))
+  (get-raw-value
+    [this]
+    (when-not (= (count this) 2)
+      (throw (IllegalArgumentException.
+               "Vector used as IMapEntry must be a pair")))
+    (let [v (this 1)]
+      (delay v))))
 
 (gen-interface
   :name    de.kotka.lazymap.ILazyMap
   :methods [[lazyAssoc [Object Object] de.kotka.lazymap.ILazyMap]])
 
 (import
-  'de.kotka.lazymap.ILazyMapEntry
   'de.kotka.lazymap.ILazyMap)
 
-(defn create-lazy-map-entry
-  [k v]
-  (reify [ILazyMapEntry]
-    ; ILazyMapEntry
-    (getRawValue [this] v)
-    ; IMapEntry
-    (key         [this] (.getKey this))
-    (getKey      [this] k)
-    (val         [this] (.getValue this))
-    (getValue    [this] (force v))
-    ; Object
-    (toString    [this] (str \[ (.getKey this) \space (.getValue this) \]))))
+(deftype LazyMapEntry [k v]
+  ILazyMapEntry
+  (get-key       [_] k)
+  (get-raw-value [_] v)
+  IMapEntry
+  (key           [_] k)
+  (getKey        [_] k)
+  (val           [_] (force v))
+  (getValue      [_] (force v))
+  Object
+  (toString      [_] (str \[ k \space (force v) \])))
 
-(defmethod print-method ILazyMapEntry
-  [#^ILazyMapEntry this #^java.io.Writer writer]
-  (.write writer (.toString this)))
+(defmethod print-method LazyMapEntry
+  [this #^java.io.Writer w]
+  (.write w (.toString this)))
 
 (defn create-lazy-map-seq
   ([inner-seq]
    (create-lazy-map-seq inner-seq nil))
   ([inner-seq metadata]
-   (reify [ISeq IObj]
-     ; ISeq
+   (reify
+     ISeq
      (first
        [this]
        (let [first-val (first inner-seq)]
-         (create-lazy-map-entry (key first-val) (val first-val))))
+         (LazyMapEntry. (key first-val) (val first-val))))
      (next
        [this]
        (when-let [inner-rest (next inner-seq)]
          (create-lazy-map-seq inner-rest metadata)))
      (more  [this]   (lazy-seq (.next this)))
-     (cons  [this o] (cons o this))
+     (cons  [this o] (create-lazy-map-seq (cons o inner-seq) metadata))
      ; IPersistentCollection
      (count [this]   (count inner-seq))
      (empty [this]   ())
-     (seq   [this]   this)
-     ; IObj
-     (withMeta [this new-metadata] (create-lazy-map-seq inner-seq new-metadata))
-     ;IMeta
-     (meta  [this]   metadata))))
+     (seq   [this]   this))))
 
 (defn create-lazy-map
   ([base]
      (without     [this k] (create-lazy-map (dissoc base k) metadata))
      ; Associative
      (containsKey [this k] (contains? base k))
-     (entryAt     [this k] (create-lazy-map-entry k (base k)))
+     (entryAt     [this k] (LazyMapEntry. k (base k)))
      ; IPersistentCollection
      (count       [this]   (count base))
      (cons
        [this o]
-       (condp instance? o
-         ILazyMapEntry     (let [#^ILazyMapEntry o o]
-                             (let [k (.getKey o)
-                                   v (.getRawValue o)]
-                               (.lazyAssoc this k v)))
-         IMapEntry         (let [#^IMapEntry o o]
-                             (let [k (.getKey o)
-                                   v (.getValue o)]
-                               (.assoc this k (delay v))))
-         IPersistentVector (if (= (count o) 2)
-                             (let [k (o 0)
-                                   v (o 1)]
-                               (.assoc this k (delay v)))
-                             (throw (IllegalArgumentException.
-                                      "Vector arg to map conj must be a pair")))
+       (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
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.