Hi Meikel, This is awesome! You just did a big chunk of what I was about to try to do :). Sorry for the late response, I've been off the grid for a few days...
With your second proposed solution, the defrecord-with-defaults macro, one can achieve very good performance while keeping some of the features that implementation inheritance provides. I'll look into your macro more closely and see if I can make it a seamless substitute for defmacro. Toni. On Sat, Jul 17, 2010 at 4:02 AM, Meikel Brandmeyer <m...@kotka.de> wrote: > Hi, > > one way to do that is using extend. > > (def defaults > {fn1 (fn ...) > fn2 (fn ...) > fn3 (fn ...)}) > > (defrecord R1 [...]) > (def R1-fns > {fn1 (fn ...)}) > > (defrecord R2 [...]) > (def R2-fns > {fn2 (fn ...) > fn3 (fn ...)}) > > (extend YourProtocol > R1 (merge defaults R1-fns) > R2 (merge defaults R2-fns)) > > Another way is the following macro: > > (defmacro defrecord-with-defaults > [record fields & protocol-default-fns] > (let [process-protocol > (fn [[protocol defaults fns]] > (let [defaults (when defaults > (->> defaults > resolve > var-get > (map (fn [[k f]] > (vector > k (cons (symbol (name k)) (next f))))) > (into {})))] > (list* protocol > (->> fns > (map #(array-map (-> % first name keyword) %)) > (apply merge defaults) > (map second))))) > split-protocols > (fn split-protocols > [p-d-fs] > (lazy-seq > (when-let [[p d & fs] (seq p-d-fs)] > (let [[fs next-p-d-fs] (split-with (complement symbol?) fs)] > (cons [p d fs] (split-protocols next-p-d-fs))))))] > `(defrecord ~record ~fields > ~@(mapcat process-protocol (split-protocols protocol-default-fns))))) > > Usage: > > (def foo-defaults > `{:bar (fn ([this# that#] nil)) > :baz (fn [this# that#] nil)}) > > (defrecord-with-defaults R [a b] > Foo foo-defaults > (bar [this that] nil) > Frob nil > (frobnicator [this] nil)) > > Note: you have to syntax-quote the functions in the default map (as for > definline). And you can have only one arity per function. Here the > corresponding expansion: > > (clojure.core/defrecord FooImpl1 [a b] > Foo > (bar [this that] nil) > (baz [this__711__auto__ that__712__auto__] nil) > Frob > (frobnicator [this] nil)) > > Sincerely > Meikel > > -- > 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 -- Antoni Batchelli - twitter: @tbatchelli , @disclojure --- email: tbatche...@gmail.com ----- web: tbatchelli.org , disclojure.org -- 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