thanks for the lengthy reply! i will play around with these suggestions. like the fact there are less parameters to pass around.
On Tue, Sep 28, 2010 at 1:10 AM, Meikel Brandmeyer <m...@kotka.de> wrote: > Hi, > > I'm not sure my solution is 100% idiomatic, but has some advantages. > General strategy: minimise macro usage. Macros are cool, but > overrated. Put as much as possible into functions. This has several > advantages like easier testing, less macro trap doors, better > readability (no # all over the place) or possibility of hotfixing of > eg. the cleanup code in with-context[1], etc. > > So my plan is: put everything in special global variables. Expose them > as options for the functions. The defaults refer to the global > variables which are set with binding. So allows for usage pattern, but > could also allow for easy testing. > > (with-context [:some option] > (init-source "bla" :some "option")) > > or > > (init-source "bla" :some "option" :context manually-crafted-context) > > Here is my try: > > (declare *context* *thread* *receivers* *sources*) > > (defn init-receiver > [topic & {:keys [context receivers] > :or {context *content* receivers *receivers*} > :as options}] > ...boring java stuff) > > (defn init-source > [topic & {:keys [context sources] > :or {context *content* sources *sources*} > :as options}] > ...boring java stuff) > > (defn publish > [topic message & {:keys [context sources] > :or {context *content* sources *sources*} > :as options}] > ...boring java stuff) > > (defn receive > [topic func & {:keys [context receivers] > :or {context *content* receivers *receivers*} > :as options}] > ...boring java stuff) > > (defn with-context* > [options thunk] > (let [context (create-context options) > thread (create-thread context) > sources (atom {}) > receivers (atom {})] > (binding [*context* context > *thread* thread > *sources* sources > *receivers* receivers] > (try > (thunk) > (finally > ... close stuff, cleanup))))) > > (defmacro with-context > [options & body] > `(with-context* ~options (fn [] ~...@body))) > > Icying (not tested though, but some quick macroexpands seem to be > promising): > > (defmacro defsugaredfn > [fnname & fntail] > (let [[docstring fntail] (let [[docstring & tail :as fntail] fntail] > (if (string? docstring) > [docstring tail] > [nil fntail])) > [metamap fntail] (let [[metamap & tail :as fntail] fntail] > (if (map? metamap) > [metamap tail] > [nil fntail])) > args (first fntail) > fntail (next fntail) > options (peek args) > options (when (map? options) options) > mod-options (merge-with into > `{:keys [~'context > ~'receivers > ~'sources] > :or {~'context *context* > ~'receivers > *receivers* > ~'sources *sources*} > :as ~'options} > options) > args (if options > (pop args) > (conj args '&)) > args (conj args mod-options)] > `(defn ~fnname > ~@(concat (when docstring [docstring]) > (when metamap [metamap]) > [args]) > ~...@fntail))) > > Use as: > > (defsugaredfn init-receiver > "with docstring! yeah!" > [topic & {:keys [some] :or {some "option"}}] > ...boring java stuff) > > or > > (defsugaredfn init-receiver > [topic] > ...boring java stuff) > > context, receivers, source and options will be captured this way and > available in the "boring java stuff" part. Another downside: you have > to take care when you cross thread boundaries. Then you have to use > bound-fn or pass the context and friend explicitely. > > (with-context [:some "option"] > ... > (bound-fn [] (init-receiver "in another thread")) > ... > (fn [] (init-receiver "in another thread" :context > context :receivers receivers) > ,... > ) > > Hope that helps. > > Sincerely > Meikel > > [1]: With a macro the client code has to be recompiled. > > -- > 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