2017-10-07 84 views
0

我是clojure的新手,我刚学过记忆功能并进行了实验。 在我看来,这个功能的存在是奇怪的。为什么我们有clojure memoize功能?

首先带副作用的功能以!

其次使用记忆很简单

为什么不Clojure的只是这样做对吗?在内存使用和性能之间有一个平衡点,但是你可以很容易地让clojure运行时将一块内存分配给函数结果。如果多次使用相同的参数调用一个函数使用缓存的结果,如果内存耗尽清除缓存并跟踪缓存命中,那么频繁调用的函数不太可能从缓存中移除。

如果我设计了这个功能,我甚至会为函数设置一个最低性能级别,这样如果函数调用比缓存检索更快,它不会被缓存。 (或者使这所有的功能如何调用工作性质。)

任何人都可以解释为什么Clojure中并没有这样做

感谢

+1

如果您可以将此功能添加到编译器中,您将会高兴Clojure社区。请记住Clojure(不像 - 说 - Haskell)不强制*函数是纯粹的。 – Thumbnail

+3

我不认为任何人都会为此感到高兴。它有很多问题。你几乎可以立即填满内存,例如,缓存一堆没人关心的无用垃圾,没有余地缓存一两件有用的东西。此外,每次函数调用都会增加大量开销以执行缓存,并测量“最低性能级别”以决定是否值得缓存。由于每个函数的运行时间变得不确定,因此性能会变得难以推理。副作用函数运行“如果感觉像”。 – amalloy

回答

4

有一个老笑话在计算机科学中,有只有两个困难的问题:

  1. 缓存失效
  2. 命名的东西

内置的memoize函数在它的功能上是一个很好的开始,在少数情况下它是有用和充分的。但它确实适合那个好笑的玩笑。这是一个有点尴尬的名字(这里的观点),它在缓存失效时失败非常严重。它假定如果一个函数被调用过,那么结果总是相关的,并且函数是纯粹的,并且不会遇到错误,并且所有的调用在所有时间都是同等相关的。现实世界是充满了练得缓存非常重要的细微差别:

  1. 许多返回值是没有用的永远
  2. 许多功能在范围无限(数学为例)
  3. 许多功能比缓存更快(数学再次)
  4. 函数具有等价的参数。这些应该在同一个班级。
  5. memoize实际上并不保证只运行一次函数。
  6. 许多功能永远不会是纯粹的(如接受网络连接)
  7. 某些参数不会影响返回值。

所有这些事情都在设计Web应用程序的缓存时发挥作用。 #5是一个有趣的例子,考虑一下如果你的函数非常慢,并且有两次调用相隔一秒,会发生什么。哪个返回值成为记忆结果?这在哪些情况下非常重要。这些细节真的很重要,特别是如果其中一个遇到不寻常的情况。

在过去的八年中,我专业地做clojure,我似乎很多次都在使用memoize,并且一旦出现不可避免的问题,它总是在短时间内被clojure.core.cache中的一个函数调用所取代。

如果你发现自己想要memoize有一个很好的机会,你会与core.cache更快乐。它提供了更多细致入微的选项以适应更多的现实世界案例。