为什么memoization不是语言功能?

时间:2009-12-19 13:51:46

标签: language-agnostic memoization

我在想......为什么我所知道的任何一种语言本身都不提供备忘录作为语言功能?

编辑:澄清一下,我的意思是该语言提供了一个关键字来指定给定的函数为memoizable,而不是每个函数都默认自动记忆,除非另有说明。例如,fortran提供关键字PURE以指定特定的功能。我想编译器可以利用这些信息来记忆调用,但我忽略了如果你声明PURE是一个带副作用的函数会发生什么。

11 个答案:

答案 0 :(得分:46)

您想要的记忆可能与编译器记忆选项提供的内容不同。

您可能知道记住最后10个左右计算的不同值是有利可图的,因为您知道该函数将如何使用。

您可能知道记住最后2或3个值是有意义的,因为您永远不会使用早于此值的值。 (斐波纳契的序列浮现在脑海中。)

您可能会在某些运行中生成大量值,而在其他运行中只会生成少量值。

你可能想要“扔掉”一些记忆值并重新开始。 (我用这种方式记忆了一个随机数生成器,所以我可以重放构建某个结构的随机数序列,而结构的其他一些参数也已经改变了。)

作为优化的记忆取决于搜索记忆值比重新计算值便宜得多。这又取决于输入请求的顺序。这对memoization数据库有影响:它是否使用堆栈,所有可能的输入值(可能非常大),桶哈希或b树的数组?

memoizing编译器必须提供“一刀切”的memoization,或者它必须提供许多可能的替代方案,以及控制替代方案的参数。在某些时候,每个人都更容易要求用户提供自己的记忆。

答案 1 :(得分:22)

因为编译器必须发出语义正确的程序。除非是referentially transparent,否则不能在不改变程序语义的情况下记忆函数。在大多数编程语言中,并非所有函数都是引用透明的(纯函数式编程语言是例外),因此您无法记住所有内容。但是,需要一种机制来检测参考透明度,这太难了。

答案 2 :(得分:12)

Clojure有一个memoize函数(http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/memoize):

memoize
function

Usage: (memoize f)

Returns a memoized version of a referentially transparent function. The
memoized version of the function keeps a cache of the mapping from arguments
to results and, when calls with the same arguments are repeated often, has
higher performance at the expense of higher memory use.

答案 3 :(得分:12)

在Haskell中,memoization is automatic为(纯)函数定义了不带参数的函数。而Wiki中的Fibonacci示例实际上是关于我能够想到的最简单的可证明示例。

Haskell可以这样做,因为你的纯函数被定义为每个时间产生相同的结果;当然,依赖于副作用的monadic函数将不会被记忆。

我不确定上限是什么 - 显然,它不会记忆超过可用内存。而且我也不确定是否在编译时发生了memoization(如果 值可以在编译时确定),或者总是发生在第一次调用函数的时间。

答案 4 :(得分:6)

因为当语言本身很容易实现时,您不应该将某些内容实现为语言功能。 memoization功能属于库,这正是大多数语言所使用的。

答案 5 :(得分:5)

A)记忆化时空交易空间。我想这可能会变成一个相当不受约束的属性,从某种意义上说,数据程序或库必须存储的数量可能会非常快地消耗大部分内存。

对于几种语言,memoization易于实现,并且易于根据给定的要求进行自定义。

作为一个例子,对大型文本进行一些自然语言处理,你不想一遍又一遍地计算文本的基本属性(字数,频率,共现,......)。在这种情况下,与内存缓存相比,与对象序列化相结合的memoization可能很有用,因为您可以在未更改的语料库上多次运行应用程序。

B)另一方面:并非所有函数或方法都为同一给定输入产生相同的输出。无论如何,有必要使用一些关键字或语法进行记忆,以及配置(内存限制,失效策略......)......

答案 6 :(得分:1)

并非所有语言本身都支持函数装饰器。我想这将是一种更通用的方法来支持而不是支持只是回忆。

答案 7 :(得分:1)

您的问题也为您学习更多语言提供了解决方案。我认为Lisp支持memoization,我知道Mathematica会这样做。

答案 8 :(得分:1)

反转问题。为什么要这样?正如有人所说,它可以放在库中,因此不需要为语言添加语法,它只适用于很难自动识别的纯函数(除非你强迫程序员注释它们)。也很难确定memoization是否会加快速度。我不认为它是编程语言的理想功能。

答案 9 :(得分:1)

我真的认为这样的选择应该是。

在数据处理任务中,存在不可变的输入数据(例如,时间序列,对于给定时间,一旦知道值,它就永远不会改变)。考虑到RAM的可承受性,如果函数结果仅取决于这些不可变数据,那么记住它是合理的,而不是每次需要时都重读。目前我(在Scala和C#中)手动引入内存存储表并编写3个函数而不是一个 - 从文件/ db / ws读取一个值,一个将其存储到内存表中,一个用于包装它们如果可用则从内存中读取,如果没有则调用原始函数。我认为这可以而且应该作为关键词实现,并在幕后完成。

答案 10 :(得分:1)

为了让memoization作为语言功能工作,会有一些要求。

  1. 编译器需要识别用于记忆的有效函数(例如,它们是引用透明的)。
  2. 运行时必须能够智能地选择备忘录,而不会降低整体性能。
  3. 在另一种语言中有一些假设,但如果我们可以通过及时编译Java VM中的热点来提高性能,那么可以肯定地编写一个自动化的memoziation系统。

    虽然非常重要,但我认为理论上可以在语言中获得性能提升(尤其是解释性语言)并且是一个值得研究的领域。