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]
     (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)))

我之前编写的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。
通常使用Maven运行支持的项目:mvn test

我维护的所有支持的项目通常也都支持 CLI/deps.edn,你可以用以下命令运行这些测试:clojure -A:test:runner

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

build-memoizer当前的通用程度是因为它需要能够支持任意缓存,这些缓存可以接受任意顺序的任意参数(因此你的辅助器只能对某些缓存有效)。
在研究这个问题时,我发现PluggableMemoization的种子函数中存在一个错误 https://clojure.atlassian.net/browse/CMEMOIZE-27
clojure.core.memoize的master分支对此问题进行了修复:而不是将derefable-seed设为公开,我增加了一个新的memoizer函数,该函数需要一个函数、一个缓存(不是一个缓存工厂)以及一个可选的种子/基本哈希表。这使得创建自定义缓存的函数变得更加容易,同时披露了较少的库内部实现。

我将尽快发布带有这一更新功能的新版本。
by
谢谢。我正在用此在https://github.com/john-shaffer/krulak/blob/ba09b5098eff2f614ffe2b98c6ed5c6fb2783dc5/src/krulak.clj#L34
我还创建了一些其他函数,它们可以访问memoize的内部。我基本上需要core.cache接口中所有内容的memoize等价物。核心.memoize中是否有任何这样的功能正在考虑添加?
by
我不太清楚你在问什么-- core.memoize是基于实现core.cache协议的可插拔memoization类型,所以存在相同的功能。你能具体说明你需要添加到core.memoize中的内容吗?你感到core.memoize的私有部分需要被用来扩展和自定义memoization,这使我感到不舒服。如果你觉得库的某个部分需要解决,可以自由开始一个新的问题线程。
by
我想我可能不太清楚如何在支持的 方式下替换PluggableMemoization。我可以访问冒号clojure.core.memoize/cache的原子,但缓存-id是私有的,给我一种印象,原子的位置可能是变化实现细节。可以依赖于这个原子吗,我还是错过了什么?
by
你是想指类似这样的事情吗?使用 memo-swap!(与快照一起使用以访问当前缓存中的内容):https://github.com/clojure/core.memoize/blob/master/src/test/clojure/clojure/core/memoize_test.clj#L207-L217

如果不是,能否用我能理解的方式解释一下你试图解决的问题,这样我就能看到你认为是 API 中缺少的东西吗?
memo-swap! 加上快照工作很好,但快照会为缓存中的每个项目创建一个新的映射,这在设置缓存中特定值的情况下会产生太多开销。我将为这件事建立一个新线程。我的其他用途在更好地理解 API 之后很适当地融入到 API 中。我确实希望有权限使用带不同参数的缓存,并且快照对此非常合适。
...