(def m (fun-map {:a 4 :b (delay (println "accessing :b") 10)}))
(def m (fun-map {:a (future (do (Thread/sleep 1000) 10)) :b (future (do (Thread/sleep 1000) 20))}))
(def m (fun-map {:a (future (do (Thread/sleep 1000) 10)) :b (delay 20)}))
(def m (fun-map {:xs (range 10) :count-keys ^:wrap (fn [m] (count (keys m))) :sum (fnk [xs] (apply + xs)) :cnt (fnk [xs] (count xs)) :avg (fnk [sum cnt] (/ sum cnt))}))
(def system (life-cycle-map {:component/a (fnk [] (reify java.io.Closeable (close [_] (println "halt :a")))) :component/b (fnk [:component/a] (reify java.io.Closeable (close [_] (println "halt :b"))))}))
(touch system) ;;start the system
(halt! system)
However, the implementation of fun-map is very different from plumbing.
- The graph in plumbing is a data structure defined by a map, but need be compiled to a function. While a fun-map is just a plain map, so no compilation there.
- Plumbing allow you compile your computation eagerly or lazily, in fact, it even use another lazy-map library. Fun-map is just map and you can put delay or future in you value for each map entry, so there is not any limit to choose.
- the compiling process can detect cyclical dependency between functions, while in a fun-map there is not such a mechanism yet.
- you can not put a separated value or function in a graph, the compilation process will remove them. In a fun-map you can keep any thing.
Because fun-map do no pre-computation, it just use clojure function call and map lookup itself, the implementation is very simple.