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

Reply via email to