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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en