Marc, Nicely done! I've done something similar before as well.
This was basically my point earlier: Dispatch tables (and maps in general), unification, and closures seem to solve the same problem, are composable, don't introduce nouns/types/metaphors, are open for extension and closed for modification, and if crafted well, can be shipped around to any reader. Using RabbitMQ and Clojure as my data format, I can easily create loosely coupled, highly cohesive services that can be replicated, redundant, etc. I think the project looks interesting, but the benefits, tradeoffs, and design decisions aren't clear to me. Paul On May 10, 11:11 am, Marc Limotte <mslimo...@gmail.com> wrote: > Hi Jeff, > > What do you think about a Map interface for this? > > I recently implemented something similar in a project of mine, which I > called an 'evaluating-map'. It's not a Web project, but the pattern is a > general one. In my case, a DSL for specifying a job to run. I want the > DSL writer to have access to a lot of data/logic which can come from a lot > of different sources (a "big ball of mud" to use your term). > > Like you, the mud-ball could contain values or functions. These functions > can have references to other values in the "ball of mud". I expanded this > to include interpolated strings (e.g. "foo is ${foo}") and collections of > values/Strings/functions which are handled recursively. My code doesn't do > anything to manage state, although users are encouraged to provide memoized > functions and a helper is provided to assist with this. > > Here's an example comparable to your example from the Kiln project. > > (def m > {:request "foo" > :uri #(build-uri (:request %)) ; an anonymous function works, or > :path (lfn [uri] (.getPath uri)) ; use lfn, a helper that returns a fn > :dispatch > (lfn [path] (condp = path > "/remove-user" :remove-user > "/add-user" :add-user > "/view-user" :view-user)) > :action! action ; assuming action is defn'ed elsewhere > ... and so on ... }) > > lfn is the helper that I mentioned-- it pulls it's args as keys from the > "ball-of-mud" and returns a memoized fn of those args. > > Eventually, you fire it. Like Kiln, the concept is that you have a bunch > of code that sets it up and then at some point you mix in a few seed values > and kick it off. My fire function does a bunch of other stuff, but the > relevant part boils down to (-> m (assoc :request req) evaluating-map), > which is used like this: > > (let [k (-> m (assoc :request req) evaluating-map) > result (try > (:action! k) > (render-template (:template k) ...other kiln data...) > ... catch)] > ; because it's a Map, you can do things like > (log/debug (select-keys k [:uri :path])) > result) > > I didn't write support for glazes and cleanup. I think glazes could be > done ring-style. Cleanup requires some extra thought. Those are nice > features of Kiln. > > I think Kiln gives you more control over the execution and state, making > things like cleanup easy. What I like about the Map interface, aside from > the convenience of being able to use standard collection functions (merge, > select-keys, dissoc, etc) is that you can construct the map from many > different sources. I.e. you can merge maps which are constructed > dynamically at different points in your flow. This was important for my > use-case, since DSL users are writing code that my core code knows nothing > about. Using the example above, a subsequent user could replace the :uri > fn: > > (merge m {:uri (lfn [request] (some-other-build-fn request))}) > > This new function would then be the input for the :path function. > > My code for this abstraction isn't isolated, but you can see it in context > of another project > here<https://github.com/TheClimateCorporation/lemur/blob/master/src/main/c...> > . > > Anyway, I like the project and thanks for sharing it. > > Marc > > On Sun, May 6, 2012 at 2:08 PM, Jeffrey Straszheim <jstra...@akamai.com>wrote: > > > > > > > > > > > The Kiln is an evaluation strategy for insanely complex functions. It was > > designed based on two things: my experience with managing several large, > > complex, ever-changing web applications in Clojure, and my experience in > > dataflow approaches to modelling. > > > I have released version 1.0.0 on Clojars. Also, there is quite a bit of > > documentation and explanation on the project Github page, including a full > > sample application presented in a somewhat “literate” style. > > > Please take a look. > > >http://github.com/straszheimjeffrey/The-Kiln > > > -- > > 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 > > Note that posts from new members are moderated - please be patient with > > your first post. > > 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 -- 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 Note that posts from new members are moderated - please be patient with your first post. 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