我正在尝试实现一个get-database
函数,该函数在第一次调用时从Monger中检索数据库引用,记住atom中的值并在后续调用中直接返回它。我目前的代码如下:
(def database (atom nil))
(defn get-database
[]
(compare-and-set! database nil
(let [db (:db (mg/connect-via-uri (System/getenv "MONGOLAB_URI")))] db))
@database)
问题是即使let
返回false(即compare-and-set!
不是database
),似乎也会评估nil
子句。有没有办法让这个懒惰地评估,所以我不会因为检索Monger连接而受到惩罚,或者这种方法是否从根本上被误导了?
答案 0 :(得分:4)
这里的问题是compare-and-set!
是一个函数,所以评估它将在调用函数之前评估所有参数。
我对缓存和重新使用一些昂贵的计算值的用例采取的典型方法是使用delay
:
采用一组表达式并生成一个Delay对象 仅在第一次强制(使用force或deref / @)时调用主体,并且 将缓存结果并在所有后续力量上返回 调用。另见 - 实现?
在你的情况下:
(def database (delay (:db (mg/connect-via-uri (System/getenv "MONGOLAB_URI")))))
现在,只要您想要获取对数据库的引用,就可以说@database
,并且在您的代码第一次实际导致延迟被取消引用时,连接将被初始化。如果您愿意,可以将呼叫包起来取消引用get-database
功能中的延迟,但这并非必要。