From aabc4f02ca49cb4e65debc79d50c24c1481a6e0a Mon Sep 17 00:00:00 2001 From: Eric Schulte Date: Sun, 23 Jan 2011 11:09:54 -0700 Subject: [PATCH] multiple improvements based on Ken Wesson's comments --- src/propagator.clj | 44 +++++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/src/propagator.clj b/src/propagator.clj index 6fcf7fd..65170f2 100644 --- a/src/propagator.clj +++ b/src/propagator.clj @@ -1,41 +1,31 @@ - -(ns - #^{:author "Eric Schulte", +(ns #^{:author "Eric Schulte", :license "GPLV3", :doc "Simple concurrent propagator system."} propagator (:use clojure.contrib.repl-utils clojure.contrib.math)) -(defmacro cell "Define a new cell." - [name state] - `(def ~name (agent ~state))) - (defn set-cell "Set the value of a cell" [cell value] - (send cell (fn [_] value))) - -(defmacro propagator "Define a new propagator." - [name in-cells out-cells & body] - `(do - (defn ~(with-meta name - (assoc (meta name) - :in-cells in-cells :out-cells out-cells)) - ~in-cells ~@body) - (doseq [cell# ~in-cells] (add-neighbor cell# ~name)) - ~name)) + (send cell (constantly value))) (defmacro run-propagator "Run a propagator, first collect the most recent values from all cells associated with the propagator, then evaluate." [propagator] - `(let [results# (apply ~propagator (map deref (:in-cells ^#'~propagator)))] - (doseq [cell# (:out-cells ^#'~propagator)] + `(let [results# (apply ~propagator (map deref (:in-cells (meta ~propagator))))] + (doseq [cell# (:out-cells (meta ~propagator))] (when (not (= @cell# results#)) - (send cell# (fn [_#] results#)))) + (set-cell cell# results#))) results#)) -(defmacro add-neighbor "Add a neighbor to the given cell." - [cell neighbor] - `(add-watcher - ~cell :send - (agent nil :validator (fn [_#] (do (future (run-propagator ~neighbor)) true))) - (fn [_# _#]))) +(defn add-neighbor "Add a neighbor to the given cell." [cell neighbor] + (add-watch cell nil (fn [_ _ _ _] (future (run-propagator neighbor))))) + +(defmacro defcell "Define a new cell." [name state] + `(def ~name (agent ~state))) + +(defmacro defpropagator "Define a new propagator." + [name in-cells out-cells & body] + `(let [v# (defn ~(vary-meta name assoc :in-cells in-cells :out-cells out-cells) + ~in-cells ~@body)] + (doseq [cell# ~in-cells] (add-neighbor cell# ~name)) + v#)) -- 2.11.4.GIT