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

欢迎!请参阅 关于 页面以了解有关此工作的更多信息。

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]
     构建memoizer
      #(PluggableMemoization. %1 (apply cache-factory %2 %3))
      f
      (derefable-seed base)
      args))

memo实现随后变为(无文档)

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

我之前写的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函数中有一个bug https://clojure.atlassian.net/browse/CMEMOIZE-27
by
clojure.core.memoize的master分支对此问题有一个修复:而不是使derefable-seed公开,我添加了一个新的memoizer函数,它接受一个函数、一个缓存(不是缓存工厂)和一个可选的种子/基本哈希表。这使创建自定义缓存函数变得更容易,同时也减少了库内部细节的暴露。

我将尽快发布包含此更新功能的新版本。
谢谢。我目前正在这里使用它
我还创建了几个其他函数,它们可以深入到memoize内部。我基本上需要memoize等价于core.cache接口中的一切。核心.memoize想要添加此类功能吗?
我不确定你在这里问的是什么——core.memoize基于一个PluggableMemoization类型,该类型实现了核心.cache协议,所以所有相同的功能都是存在的。你能具体说明你想要添加到core.memoize中的内容吗?你感觉需要使用核心.memoize的私有部分以扩展和自定义memoization,这让我感到不舒服。对于你认为需要解决的问题的每个部分,都可以开一个新的问题线程。
我想可能我不太清楚如何更换PluggableMemoization。我可以访问:clojure.core.memoize/cache原子的值,但是由于cache-id是私有的,给我的印象是这个原子的位置可能是实现细节,可能会改变。依赖这个原子是可以的吗?我还是遗漏了其他东西?
您的意思是否像这样:使用 memo-swap!(与快照结合以访问当前缓存的值)?请参阅链接

如果不是,能否以我可以了解您认为在API中缺少什么的方式解释您试图解决的问题?
memo-swap! 结合快照工作良好,但快照在每次创建时都会创建一个新的带有缓存中每个项目的映射,这对设置缓存中的特定值来说开销太大。我将为这个问题创建一个新的帖。我了解API后,其他用法很融洽地加入了API。我确实希望能够在具有不同参数的缓存中交换,快照对这完美适用。
...