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

Reply via email to