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

由于缓存元素是derefable的事实应该是实现细节,因此可能存在一种更好的方法来提供此类扩展。

这肯定是个好主意。我编写了一个辅助函数来抽象这些细节。

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

我维护的所有 Contrib 项目也支持 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函数,它接受一个函数、一个缓存(不是缓存工厂)以及可选的种子/基本哈希表。这使得创建自定义缓存的函数更加容易,同时减少了暴露库的内幕。

我将很快推出更新功能的新版本。
by
谢谢。我现在正在这里使用它。
我还创建了一些其他函数,这些函数可以深入到memoize内部。我基本上需要memoize的core.cache接口的所有功能的等价物。在core.memoize中会有类似功能吗?
by
我不太清楚你在这里问的是什么 — core.memoize是基于一个可插拔的Memoization类型,该类型实现了core.cache协议,所以所有相同的函数都存在。你能具体说明你认为需要添加到core.memoize中吗?你感觉需要用到core.memoize的私有部分来扩展和自定义缓存,这让我感到不安。你可以为每个需要解决的库部分发起一个新的问题线程。
by
我想我可能没有弄清楚如何替换PluggableMemoization。我可以访问:clojure.core.memoize/cache原子,但是cache-id是私有的,给我一个印象原子位置是实现细节,可能会改变。依赖这个原子可以吗,或者我在漏掉什么吗?
您是指这类事物吗: https://github.com/clojure/core.memoize/blob/master/src/test/clojure/clojure/core/memoize_test.clj#L207-L217 使用 memo-swap!(与快照结合以访问当前缓存的值)?

如果不是,能否用我可以理解的方式来解释您正在尝试解决的问题?这样我可以看到您认为在 API 中缺少什么。
memo-swap! 加上快照是可行的,但是快照每次都在缓存中为每个项目创建一个新的映射,这对于设置缓存中特定值的场景来说开销太大。我将为那个问题创建一个新的帖子。一旦我更好地理解了 API,其他用途很适合放入 API 中。我真的想要能够使用不同的参数来交换缓存,快照对此非常完美。
...