fogus (owner)

Revisions

gist: 163066 Download_button fork
public
Public Clone URL: git://gist.github.com/163066.git
Embed All Files: show embed
lazy-map-new-new.clj #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
(ns #^{:doc "Lazy map, a map whose values are evaluated lazily.
 
This library depends on the \"New new\" feature in Clojure,
http://www.assembla.com/wiki/show/clojure/New_new
 
Based on Meikel Brandmeyer's gen-class implementation at
http://kotka.de/projects/clojure/lazy-map.html"
       :author "Stuart Sierra"}
  lazy-map)
 
(defn make-lazy-map
  "Returns a lazy map around base-map. Retrieving keys from the lazy
map will call force on the corresponding value in the base map.
 
Lazy maps will normally be created with lazy-map and lazy-assoc."
  [base-map]
  (new [clojure.lang.Associative clojure.lang.IPersistentMap] this
       ;; Associative
       (containsKey [key] (contains? base-map key))
       (entryAt [k] (new [clojure.lang.IMapEntry]
                         (key [] k)
                         (val [] (force (get base-map k)))
                         (getKey [] k)
                         (getValue [] (force (get base-map k)))))
       (assoc [key value] (assoc base-map key value))
       (valAt [key] (force (get base-map key)))
       (valAt [key default] (if (contains? base-map key)
                              (force (get base-map key))
                              default))
 
       ;; IPersistentMap
       (assocEx [key value] (if (contains? base-map key)
                              (throw (Exception. "Key already present"))
                              (assoc base-map key value)))
       (without [key] (make-lazy-map (.without base-map key)))
       ;; IPersistentMap also defines assoc(), cannot duplicate here
 
       ;; IPersistentCollection
       (count [] (count base-map))
       (iterator [] (clojure.lang.SeqIterator. (. this seq)))
       (conj [obj] (assoc this (key obj) (val obj)))
       (cons [obj] (assoc this (key obj) (val obj)))
       (seq [] (map (fn [k] (find this k)) (keys base-map)))))
 
(defmacro lazy-assoc
  "Lazily assoc's values into m, which may be a lazy map or an
ordinary map. Keys are evaluated immediately; values are wrapped in
delay and will be forced on retrieval."
  [m & keyvals]
  `(make-lazy-map (assoc ~m ~@(mapcat (fn [[k v]]
                                        [k (list 'delay v)])
                                      (partition 2 keyvals)))))
 
(defmacro lazy-map
  "Creates a lazy map. Keys are evaluated immediately; values are
wrapped in delay and will be forced on retrieval."
  [& keyvals]
  `(lazy-assoc {} ~@keyvals))