1

我正在尝试实现一个get-database函数,该函数在第一次调用 Monger 时从 Monger 检索数据库引用,记住原子中的值并在后续调用中直接返回它。我当前的代码如下所示:

(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问题是即使compare-and-set!返回 false(即databaseis not ) ,该子句似乎也会被评估nil。有没有办法让这个懒惰地评估,这样我就不会受到检索 Monger 连接的惩罚,或者这种方法从根本上被误导了?

4

1 回答 1

4

这里的问题是它compare-and-set!是一个函数,因此评估它会在调用函数之前评估所有参数。

对于缓存和重用一些计算成本高的值的用例,我采用的典型方法是delay

获取一个表达式主体并生成一个延迟对象,该对象仅在第一次被强制时调用主体(使用 force 或 deref/@),并将缓存结果并在所有后续强制调用时返回它。另请参阅 - 实现了吗?

在你的情况下:

(def database (delay (:db (mg/connect-via-uri (System/getenv "MONGOLAB_URI")))))

现在,您可以在@database任何时候说想要获取对数据库的引用,并且在您的代码第一次实际导致延迟被取消引用时,连接将被初始化。如果您愿意,可以将调用包装起来以取消引用函数内的延迟get-database,但这不是必需的。

于 2014-10-13T17:16:23.833 回答