我正在尝试编写以下函数:
(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)))
cache-get的参数是:
(def ^:dynamic *my-local-cache*)
k
,一键,类似于:foo
func
,一个函数,如果值不存在则被调用该功能的行为是:
k
存在,只需返回值k
不存在,(1)通过调用(func)
计算它并且(2)将其存储在缓存中我面临的问题是我显然可以不做(set! dynamic-var ...)
,因为函数不知道我会将它传递给动态绑定的var并且认为dynamic-var是一个常规变量。
将该函数重写为宏 - 这很好,但除非绝对必要,否则我不想使用宏。
我的问题:有没有办法在不使用宏的情况下实现cache-get
?
[另外,我希望这是一个动态变量,而不是原子]
谢谢!
我尝试var-set
的建议。我收到以下错误:
(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
答案 0 :(得分:1)
要回答这个问题:您需要var-set
而不是set!
。
快速提问:如果您传入变量,是否真的需要动态变量?
[另外,我希望这是一个动态变量,而不是原子]
你可以扩展吗?看起来原子似乎是一个更合乎逻辑的选择。您是否需要该缓存的特定于线程的版本?
更新:示例电话:
(cache-get #'*query-ctx* [:foo-key] (fn [] :foo-value))