Maps that satisfy Clojure's map interactions but delay computing their values until the value is accessed.
This library provides a new Clojure data type, the lazy map. Lazy maps act just like regular (persistent) maps, except that their values are not computed until they are requested. Please see the unit tests for examples of the exact behavior of lazy maps.
Start by requiring the namespace:
(require '[lazy-map.core :as lm])
You can then construct a lazy map using the literal->lazy-map macro.
(def m (lm/literal->lazy-map
{:a (do (println "resolved :a") "value :a")
:b (do (println "resolved :b") "value :b")}))
; => #'user/m
; => {:a <unrealized>, :b <unrealized>}
When you request a value from the map, it will be evaluated and its value will be cached:
(:a m)
; => resolved :a
; => "value :a"
(:a m)
; => "value :a"
You can assoc values onto lazy maps just like regular maps. If you
assoc a delay, it will be treated as an unrealized value and not
forced until necessary:
(assoc (lm/literal->lazy-map {}) :a 1 :b (delay 2))
; => {:a 1, :b <unrealized>}
Lazy maps are very lazy. In practice, this means they probably will
not compute their values until absolutely necessary. For example,
taking the seq of a lazy map does not force any computation, and map
entries have been made lazy as well:
(def m (lm/literal->lazy-map
{:a (do (println "resolved :a") "value :a")
:b (do (println "resolved :b") "value :b")}))
; => #'user/m
(dorun m)
; => nil
(keys m)
; => (:a :b)
(key (first m))
; => :a
(val (first m))
; => resolved :a
; => "value :a"
You can also initialize a lazy map from a regular map, where delays are taken as unrealized values:
(lm/lazy-map {:a 1 :b (delay 2)})
; => {:a 1, :b <unrealized>}
mergeMerges two lazy maps and preserves their laziness.
(def one (lm/lazy-map {:a (delay (+ 1 2 3)) :b :b-val}))
; => #'user/one
(def two (lm/lazy-map {:a (delay (+ 4 5)) :c :c-val}))
; => #'user/two
(def merged (lm/merge one two))
; => #'user/merged
one
; => {:a <unrealized>, :b :b-val}
two
; => {:a <unrealized>, :c :c-val}
merged
; => {:c :c-val, :a <unrealized>, :b :b-val}
(get merged :a)
; => 9
one
; => {:a <unrealized>, :b :b-val}
two
; => {:a 9, :c :c-val}
deep-mergeDeep merges two lazy maps and preserves their laziness.
(def one (lm/literal->lazy-map
{:a {:c (+ 1 2 3)}
:b {:d (+ 5 6 7)}}))
; => #'user/one
(def two (lm/literal->lazy-map
{:a {:c "cccc"}
:b {:e "eeee"}}))
; => #'user/two
(def merged (lm/deep-merge one two))
; => #'user/merged
one
; => {:b <unrealized>, :a <unrealized>}
two
; => {:b <unrealized>, :a <unrealized>}
merged
; => {:a <unrealized>, :b <unrealized>}
(get merged :a)
; => {:c "cccc"}
(get merged :b)
; => {:e "eeee", :d <unrealized>}
(get-in merged [:b :d])
; => 18
merged
; => {:a {:c "cccc"}, :b {:e "eeee", :d 18}}
one
; => {:b {:d 18}, :a {:c <unrealized>}}
two
; => {:b {:e "eeee"}, :a {:c "cccc"}}
force-mapRealizes all lazy values in a map.
(lm/force-map
(lm/lazy-map {:a (delay :foo) :b :bar}))
; => {:a :foo, :b :bar}
freeze-mapReplace all unrealized values in a map.
(lm/freeze-map :quux
(lm/lazy-map {:a (delay :foo) :b :bar}))
; => {:a :quux, :b :bar}
Others laziness preserving variants of common functions:
select-keysmap-keysmap-valsfilter-keysLazy maps automatically avoid realizing their values when they are converted
to strings using str, pr-str, or print-dup and instead will display
<unrealized> placeholders.
Features unique to com.guaranteedrate/lazy-map:
seq and reduce-kv)Features unique to malabarba/lazy-map:
Can you improve this documentation? These fine people already did:
Paul Rutledge & Radon RosboroughEdit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |