Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does memoize interact with binding in Clojure?

Does memoize keep track of changes to binding which may make returning a computation it has stored incorrect?

For example if I have a function foo such as:

(defn foo [bar baz]
 ...
   (let [config-val *config-val*]
    ...)
 )

which I contain within a binding so I can change the value of *config-val*, does memoizing it mean that if I change the value of *config-val*, but not the parameters to it that it will not recompute the value of the function? Instead it will give me the value of the function with the old configuration?

like image 722
toofarsideways Avatar asked Feb 23 '23 04:02

toofarsideways


2 Answers

In Clojure 1.3.0 memoize doesn't keep track of rebinding.

user=> (def ^:dynamic *x* 5)
#'user/*x*
user=> (def f (memoize #(+ *x* %)))
#'user/f
user=> (f 1)
6
user=> (binding [*x* 6] (f 1))
6
user=> (binding [*x* 7] (f 1))
6

Additionally,

user=> (binding [*x* 7] (f 3))
10
user=> (f 3)
10
user=> *x*
5
like image 144
Jan Avatar answered Mar 06 '23 07:03

Jan


memoize does not account for binding, this can be confirmed by looking at the source where the map in the atom is keyed only by the arguments. Indeed a function with dynamic rebinding is not "referentially transparent" (i.e. it cannot be replaced with its value).

Is there something that prevents you from passing the *config-val* as an argument, at least to the function you wish to memoize?


user=> (source memoize)
(defn memoize
  "Returns a memoized version of a referentially transparent function. The
  memoized version of the function keeps a cache of the mapping from arguments
  to results and, when calls with the same arguments are repeated often, has
  higher performance at the expense of higher memory use."
  {:added "1.0"}
  [f]
  (let [mem (atom {})]
    (fn [& args]
      (if-let [e (find @mem args)]
        (val e)
        (let [ret (apply f args)]
          (swap! mem assoc args ret)
          ret)))))
like image 42
Alex Stoddard Avatar answered Mar 06 '23 07:03

Alex Stoddard