Created
August 6, 2009 00:43
-
-
Save fogus/163066 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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