缓存API是一个奇怪的选择。因为它们是不可变的缓存,所以任何通常会在可变缓存中更改某些元数据(TTL、使用数据等)的操作都必须返回缓存的新实例。
在实际的缓存API上面,还构建了一个“类似映射”的API,以便可以在这些对象上使用Clojure的get、assoc、dissoc操作,但这个外观可以(并且确实)有一些奇怪的情况,比如检查项是否在缓存中,然后查找它(并发现它已“消失”)之间的竞态条件——即便缓存本身是不可变的。这给上游用户带来了问题,例如core.memoize必须包含spin/retry逻辑以避免错误地返回nil。
这就是为什么不完全不可变的哈希表语义,所以我添加了包装命名空间,它提供了一种更直观的“可变缓存”(通过将不可变缓存包裹在atom中),但这些缓存的安全API并非真正的“类似映射”:lookup-or-miss是使用最安全的函数,它提供了一种避免竞态条件和重复执行的方式,但仍然可以在需要时按需查找可以(重新)计算所需值。
在创建后“初始化”缓存,并使用新的值哈希表是一种内在的变异操作,同样“驱逐”也是。为“类似映射”提供get操作是一个方便之处,但只有在你愿意在请求的缓存条目已过期时返回nil(或“缺失”值)的情况下才是如此。
如readme文件中所述:“core.cache API难以正确使用。”并且链接到了这个
https://dev.to/dpsutton/exploring-the-core-cache-api-57al,其中讨论了将缓存当作“仅仅是映射”来对待所导致的野外错误。