Skip to content

Instantly share code, notes, and snippets.

@fogus
Created August 6, 2009 00:43
Show Gist options
  • Save fogus/163066 to your computer and use it in GitHub Desktop.
Save fogus/163066 to your computer and use it in GitHub Desktop.
(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))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment