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

由于缓存元素是可deref的事实是预期的实现细节,因此可能会有提供这种扩展的更好的方式。

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

   (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。
by
通常使用 Maven 运行 contributed 项目:mvn test

我维护的所有 contributed 项目也通常支持 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
clojure.core.memoize 的 master 分支已经解决这个问题了:而不是将 derefable-seed 公开,我添加了一个新的 memoizer 函数,它接受一个函数、一个缓存(不是一个缓存工厂)以及一个可选的种子/基本哈希表。这使得创建自定义缓存函数变得更容易,同时公开了更少的库内部细节。

我将在“不久的将来”发布包含此更新功能的全新版本。
谢谢。我现在正在这里使用它。
我还创建了一些其他函数,它们深入到 memoize 内部。我基本上需要核心.cache 接口中的所有内容的 memoize 等效物。核心.memoize 是否有添加类似功能的项目计划?
我不确定你在这里问的是什么——core.memoize 是基于 PluggableMemoization 类型,该类型实现了核心.cache 协议,因此具有相同的功能。你能具体说明你想添加到 core.memoize 中什么?我认为你感觉私有的 core.memoize 部分需要使用来扩展和自定义缓存,这让我感到不舒服。如果你觉得库的某个部分需要解决,欢迎发起新的问题线程。
我觉得我对如何使用PluggableMemoization并不是很清楚。我可以访问冒号clojure.core.memoize/cache原子,但cache-id私有使我感觉到原子的位置可能是实现细节,可能会改变。我可以依赖这个原子吗?还是说我还遗漏了些什么?
by
你是指这类东西吗?https://github.com/clojure/core.memoize/blob/master/src/test/clojure/clojure/core/memoize_test.clj#L207-L217,使用memo-swap!(结合快照来访问当前缓存中的内容)?

如果不是,能否用我能理解的方式来解释你试图解决的问题,这样我才能知道你在API中看到了什么遗漏?
by
memo-swap! 与快照结合是有效的,但快照创建了一个包含缓存中所有项目的新的map,这对设置缓存中的特定值来说开销太大。我将为这个问题创建一个新的线程。我的其他用途在熟悉API后非常契合API。我确实想要使用不同参数来交换缓存,快照对此非常完美。
...