Clojure 2024调查中分享您的想法!

欢迎!请参阅关于页面以获取更多关于如何运作的信息。

0
core.memoize

用例:我有这段代码效果很好

(require '[clojure.core.cache :as cache])
(require '[clojure.core.memoize :as memo])
(import 'clojure.core.memoize.PluggableMemoization)

(defn lru-ttl-cache [base threshold ttl]
  (-> base
      (cache/lru-cache-factory :threshold threshold)
      (cache/ttl-cache-factory :ttl ttl)))

(defn lru-ttl-memo
  ([f base threshold ttl]
   (memo/build-memoizer
      #(PluggableMemoization. %1 (lru-ttl-cache %4 %2 %3))
      f
      threshold
      ttl
      (@#'memo/derefable-seed base))))

但它依赖于一个私有变量。这应该真正是公开的,这样客户端就能更轻松地提供自己的实现。

顺便说一句,出色的库。我喜欢在Clojure生态系统中工作。

1 答案

+1

编辑
 
最佳回答

JIRA问题创建: https://clojure.atlassian.net/browse/CMEMOIZE-28

可能有一种更好的方法来提供此类扩展,因为缓存元素是可解引用的应该被视为实现细节。

这可能是个好主意。我写了一个辅助函数来抽象细节

   (defn build-helper [cache-factory f base & args]
     (build-memoizer
      #(PluggableMemoization. %1 (apply cache-factory %2 %3))
      f
      (derefable-seed base)
      args))

这样一来,内置记忆实现就变成了(不包含文档)

   (defn memo
     ([f] (memo f {}))
     ([f seed]
      (build-helper cache/basic-cache-factory f seed)))

我将 earlier lru-ttl-memo 函数简化为

   (def lru-ttl-memo
     (partial memo/build-helper lru-ttl-cache))

这种方法确实大大提高了简洁性,并且与实现细节无关。

代码更改在 https://github.com/john-shaffer/core.memoize/commit/669febe3af7f325de43cab82ab7d09469fd148a1

我实在不知道你通常是如何运行测试的。我必须将代码链接到一个 leiningen 项目中,热修复它,然后调用 clojure.test/run-tests。
by
贡献项目通常使用 Maven 运行:mvn test

我维护的所有贡献项目一般也支持 CLI/deps.edn,你可以使用以下命令运行测试:clojure -A:test:runner

可选地提供要使用的 Clojure 版本的别名:clojure -A:test:runner:1.8

build-memoizer 目前之所以如此通用,是因为它需要能够支持任意缓存,这些缓存可以以任意顺序接受任意参数(所以你的辅助函数只能适用于某些缓存)。
by
在查看这个时,我发现 PluggableMemoization 的 seed 函数存在一个错误 https://clojure.atlassian.net/browse/CMEMOIZE-27
by
clojure.core.memoize的主分支为此修复了一个问题:而不是公开derefable-seed,我增加了一个新的memoizer函数,它接受一个函数、一个缓存(不是一个缓存工厂)和一个可选的种子/基本哈希表。这使得创建自定义缓存函数更加容易,同时减少了库内部结构的暴露。

我会很快发布一个带有此更新功能的新版本。
谢谢。我现在在<_apps/>使用它:https://github.com/john-shaffer/krulak/blob/ba09b5098eff2f614ffe2b98c6ed5c6fb2783dc5/src/krulak.clj#L34
我还创建了几个其他函数,它们可以深入到memoize内部。我基本上需要core.cache接口中的memoize等价物。core.memoize是否有添加此类功能的计划?
我不确定你在这里问什么 -- core.memoize依赖于一个实现了核心.cache协议的可插拔memoization类型,因此所有的相同功能都存在。你能具体说明你需要添加到core.memoize中的功能吗?我觉得使用核心.memoize的私有部分来扩展和定制memoization并不舒服。请随时创建新的问题线程,以解决你感觉需要解决的问题。
我猜我不太清楚如何切换到可插拔memoization。我可以访问:clojure.core.memoize/cache原子,但cache-id是私有的,给我留下了一个印象,即原子的位置可能是实现细节,可能会更改。可以依赖这个原子,还是我在错过什么?
您是指这类东西吗?使用memo-swap!(结合快照来访问当前缓存的值):https://github.com/clojure/core.memoize/blob/master/src/test/clojure/clojure/core/memoize_test.clj#L207-L217

如果不是,能否解释您想解决的问题,这样我才能了解您认为API中缺少了什么?
memo-swap! 加上快照功能可以使用,但是快照每次都会创建一个包含缓存中所有条目的新映射,这对于在缓存中设置特定值的情况来说是过重的开销。我将为新线程创建一个新的帖子。我的其他用法在实际理解API后非常适宜。我希望能够用不同的参数替换缓存,快照在这方面很完美。
...