Hi Max, Clojure has watchers on IRefs which can do most of what you are describing. auto-agent by SS in contrib allows you to define formula which are automatically updated (inspired by cells - search for cells on lib page and group). This gives a simple rule system, leaving just the the GUI interaction - which is simple also! Your specific example is not far from http://github.com/timothypratley/strive/blob/c430759c4a46f1a37c272d7448975b6bc24951b0/src/clj/cells.clj however in your case you would want to use an auto-agent to calculate the dependency. Also you want your GUI updating back to the formulas, again someone has done this for textboxes: http://bitbucket.org/ksojat/neman/src/tip/src/net/ksojat/neman/cells.clj
So I think you can achieve a lightweight solution quite easily using these parts. However if you are interested in more complete 'rules' systems then I suggest searching for Datalog on this group. JS is implementing Datalog logic querying and has already made great progress. hoeck wrote a wrapper for IRIS reasoner with macro support (DSL style) which allows you to write and query rules. Regards, Tim. On Feb 20, 9:04 pm, max3000 <maxime.lar...@gmail.com> wrote: > Hi, > > I'm new to clojure and lisp in general. I'm trying semi-porting a real > world application but at this time I lack patterns to reason about > clojure solutions to problems. I thought I'd ask the community about > one such problem I’m facing. > > To give a simple example for the following discussion, suppose we have > the following: > - A "temperature" fact that is updated by some external connection to > a thermometer. > - A "heater on" fact that depends on the temperature. If the > temperature is, say, < 20 degrees true otherwise false. > > - Requirements - > We want to have a collection of "facts", all mutable (i.e. they will > change over time). > Each fact is displayed in a GUI. So, there must be a callback > functionality for when the fact changes (observer pattern, GUI being > the observer). > Some facts are "standalone" while others are based on other facts. In > effect, these other facts are observers of the standalone facts (or of > other dependent facts). > Any component (GUI included) can change any fact anytime. When this > happens, all dependent facts must be recalculated and all observers > called. > > I implemented this in Java like so: > - Fact class implements observer pattern (w/ PropertyChangeSupport) > - GUI linked to all facts through addObserver > - Rules based engine (drools) to update facts when they change (uses > addPropertyChnageListener/removePropertyChangeListener implemented by > facts). Whenever a fact change Drools refire rules (Drools handles > dependencies). > > Drools is great but is rather heavy for my needs. My rules/ > dependencies are really not that complicated. Besides, I would much > rather have them as a series of clojure functions. > > *** > At this point, I'm a bit lost trying to match these requirements to a > clojure design. I suppose: > > - The facts must be referenced by some unique ID, probably a keyword. > - The Fact class should be ported to a structmap + related functions. > - Fact should include a function to set it. (If the set doesn’t change > anything, no callbacks are called). > - Fact should include a collection containing callback functions. > Anyone can hence “register” their callback. BUT: how to handle > unregistrations? Is this a simple matter of passing the same function > that was used to register? > - The dependencies are really not part of the facts themselves. I > should handle them as a series of clojure functions (or should I?). > E.g.: > > (defn rule1 [] (set-fact :heater-on (> (get-fact :temperature) 20))) > > - But should I also register dependencies myself? E.g: > > (add-fact-observer :temperature rule1) > > - Is there a way to make this automatic given that my rule (rule1) > already contained this information? > > - And what about the GUI (in Java)? Basically, each GUI element knows > what fact it is bound to, so the GUI code itself drives the > addObserver’s. So, I would need to expose an interface in clojure. > > (proxy someJavaInterface observer fact-in-java > (fn [] (add-fact-observer fact-in-clojure (fn [] …callback > observer…))))) > > - ??? How to make a mapping between fact-in-java and fact-in-clojure? > > I could go on but I think that is more than enough. > > Is my basic design sound? What about the questions I face? (Automatic > detection of dependencies, mapping between keywords and something java > can muster, etc.) > > I’m really not looking for a complete how to, just general guidance in > the design. Of course, code fragments are always welcome. ;) > > If you have made it this far, thanks! > > Max --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---