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

Reply via email to