Clojure: defRecord, defProtocol: doing expensive calculation only once

clojure

Solution

I'd suggest wrapping the logic to call the expensive operation once in a constructor function, and storing the result as a regular value in the record:

(defprotocol ICat "Foo"
  (meow [cat]))

(defrecord Cat [a b] "Cat"
  ICat
  (meow [cat] (:meow cat)))

(defn make-cat [a b]
  (assoc (->Cat a b) :meow (some-expensive-operation a b)))

When your code gets more complex I find that you often want to define your own constructor functions in any case.

Note that you might also want to consider wrapping the expensive operation in a lazy sequence or a delay so that it only gets computed if needed.

Problem

Context Consider the following piece of code ``` (defprotocol ICat "Foo" (meow [cat])) (defrecord Cat [a b] "Cat" ICat (meow [cat] (some-expensive-operation a b))) ``` Question Is there a way I can throw a let somewhere into there? I would prefer that (some-expensive-operation a b) is evaluated exactly once, at the time I execute ``` (->Cat a b) ``` so that at the time of (meow cat), it just returns the pre-cached value, rather than recalculate it on the fly. So for example: ``` [1] (let [x (->Cat a b)] [2] (meow x) [3] (meow x) [4] (meow x)) ``` I want (some-expensive-operation) to be evaluated exactly once at [1], then for [2], [3], [4] it just returns the old value.

Original source