Just to be clear, by "mixin" you're referring to merging two maps of
functions?

Have you considered using composition instead of mixins?

- James

On 23 November 2015 at 20:01, William la Forge <laforg...@gmail.com> wrote:

> When an object is built from a map, aggregating mixins is a trivial
> operation. But when a mixin needs to be closed, it is better to have a
> common mechanism to manage a stack of the close functions of all the
> aggregated mixins than to depend on application logic to do so. Case in
> point, I'd like to use an actor mixin or an alternative async channel mixin
> when composing a database. The async channel mixin will require a close but
> the actor mixin will not. So I developed the closer mixin to handle the
> calls to both the async channel and db file close functions. The database
> will only know the closer's do-close method. And it is the responsibility
> of the async channel and the db file mixins to register their close
> functions with the closer mixin.
>
>
> My inspiration is Stuart Sierra's component library
> <https://github.com/stuartsierra/component>. But I am not handling
> dependencies per say, only managing a stack of close functions. And the
> "components" are only functions and atoms added to a common map structure,
> not records or deftypes. The result is a very lightweight pattern for
> components. The closer code itself is a lock-free mixin that gets added to
> the common map as needed when the on-close method is called.
>
> For more information, see Closer
> <https://github.com/laforge49/aatree/wiki/Closer>.
>
> (ns aatree.closer
>   (:require [clojure.tools.logging :as log]))
>
> (set! *warn-on-reflection* true)
>
> (defn on-close [f opts]
>   (let [fsa (:closer-fsa opts)]
>     (if fsa
>       (do
>         (swap! fsa
>                (fn [fs]
>                  (if fs
>                    (conj fs f)
>                    (atom (list f)))))
>         opts)
>       (assoc opts :closer-fsa (atom (list f))))))
>
> (defn- do-closer [fs opts]
>   (when fs
>     (try
>       ((first fs) opts)
>       (catch Exception e
>         (log/warn e "exception on close")))
>     (recur (next fs) opts)))
>
> (defn do-close [opts]
>   (let [fsa (:closer-fsa opts)]
>     (if fsa
>       (let [fs @fsa]
>         (if fs
>           (if (compare-and-set! fsa fs nil)
>             (do-closer fs opts)
>             (recur opts)))))))
>
> --
> 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 unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to