Assume we want to memoize a function that is part of a protocol extended
to some user-defined record, like so:

(defprotocol SomeOps (someop [_]))
(defrecord AImp [x] SomeOps (someop [me] (comment magic here)))

one quite heavy-weight way of doing is includes a couple of indirections:

(defn ^:private mimp-someop [me]
 (println "working with" me)
 (:x me))

(def ^:private memoized-mimp-someop (memoize mimp-someop))

(defrecord MImp [x] SomeOps (someop [me] (memoized-mimp-someop me)))

(someop (MImp. 23))
; working with #user.MImp{:x 23}
; 23
(someop (MImp. 23))
; 23

a cleaner? way is to use one defn less and one lambda more..
(def ^:private limp-someop (memoize (fn [me] (println "working with" me)
(:x me))))
(defrecord LImp [x] SomeOps (someop [me] (limp-someop me)))

(someop (LImp. 17))
; working with #user.LImp{:x 17}
; 17
(someop (LImp. 17))
; 17

of course we can inline the def, can't we?

(defrecord IImp [x]
 SomeOps
 (someop [me] ((memoize (fn [myself] (println "working with" myself) (:x
myself))) me)))

Hmm seems we can't:
(someop (IImp. 11))
; working with #user.IImp{:x 11}
; 11
(someop (IImp. 11))
; working with #user.IImp{:x 11}
; 11

what's wrong? we're recreating the memoized version each time. let/fn to
the rescue:


(defrecord HImp [x]
SomeOps
(someop [me]
 ; could as well go (memoize (fn [_] (println "working with" me) x)) here..
 (let [yay (memoize (fn [myself] (println "working with" myself) (:x
myself)))]
  (yay me))))

but wait, the let (or letfn) will still be re-executed each time. We can
move the let outside the defrecord, of course, but then we could as well
go with (def ^:private), no?

So is there a way to do it cleaner without resorting to using the
map/implementation (detail) form of protocol extension?

TIA,
-Martin

-- 
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