adding tangled source files to the repo
[propagator.git] / src / propagator.clj
blob6fcf7fd5110c6a54c01afa7770938eb7dbe1a5a1
2 (ns
3     #^{:author "Eric Schulte",
4        :license "GPLV3",
5        :doc "Simple concurrent propagator system."}
6   propagator
7   (:use clojure.contrib.repl-utils clojure.contrib.math))
9 (defmacro cell "Define a new cell."
10   [name state]
11   `(def ~name (agent ~state)))
13 (defn set-cell "Set the value of a cell" [cell value]
14   (send cell (fn [_] value)))
16 (defmacro propagator "Define a new propagator."
17   [name in-cells out-cells & body]
18   `(do
19      (defn ~(with-meta name
20               (assoc (meta name)
21                 :in-cells in-cells :out-cells out-cells))
22        ~in-cells ~@body)
23      (doseq [cell# ~in-cells] (add-neighbor cell# ~name))
24      ~name))
26 (defmacro run-propagator
27   "Run a propagator, first collect the most recent values from all
28 cells associated with the propagator, then evaluate."
29   [propagator]
30   `(let [results# (apply ~propagator (map deref (:in-cells ^#'~propagator)))]
31      (doseq [cell# (:out-cells ^#'~propagator)]
32        (when (not (= @cell# results#))
33          (send cell# (fn [_#] results#))))
34      results#))
36 (defmacro add-neighbor "Add a neighbor to the given cell."
37   [cell neighbor]
38   `(add-watcher
39     ~cell :send
40     (agent nil :validator (fn [_#] (do (future (run-propagator ~neighbor)) true)))
41     (fn [_# _#])))