Background
I'm trying to write the following function:
(defn cache-get [dynamic-var k func]
(if-let [v (get-in dynamic-var k)]
v
(let [ans (func)]
(set! dynamic-var (assoc-in dvar k ans))
ans)))
The arguments to cache-get are:
- dynamic-var, something like
(def ^:dynamic *my-local-cache*)
k
, a key, something like:foo
func
, a function, to be called if the value does not exist
The behavior of the function is:
- if the key
k
exists, just return the value - if the key
k
does not exist, (1) compute it by calling(func)
and (2) store it in the cache
Problem I am facing
The problem I am facing is that I apparently can not do (set! dynamic-var ...)
, because the function has no idea I will be passing it a dynamically bound var and thinks dynamic-var is a regular variable.
My current option:
Rewrite the function as a macro -- which is fine, but I prefer to not use macros unless absolutely necessary.
My question: is there a way to implement cache-get
without using macros?
[Also, I want this to be a dynamic-var, not an atom]
Thanks!
Edit 1
I try suggestion of var-set
. I get the following error:
(def ^:dynamic *query-ctx* {})
(defn cache-get [dynamic-var k func]
(if-let [v (get-in dynamic-var k)]
v
(let [ans (func)]
(var-set dynamic-var (assoc-in dynamic-var k ans))
ans)))
(cache-get *query-ctx* [:foo-key] (fn [] :foo-value))
;; clojure.lang.PersistentArrayMap cannot be cast to clojure.lang.Var