为什么memoization不是语言功能?

Ste*_*ini 35 language-agnostic memoization

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

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

Joh*_*ohm 47

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

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

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

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

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

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

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


jas*_*son 22

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

  • 你必须有一些代表能够downvote - 不太可能是机器人. (2认同)

pet*_*ust 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.
Run Code Online (Sandbox Code Playgroud)

  • 另请注意,它不到10行代码. (2认同)
  • @一个.Levy:此外,它来自`clojure.core`,这基本上意味着它是一种内置语言功能,虽然不像10种左右的"特殊形式"那样基本.正如你所说,Lisp中的规则是不同的:) (2认同)

Mar*_*off 12

在Haskell中,对于您定义的不带参数的(纯)函数,memoization是自动的.而Wiki中的Fibonacci示例实际上是关于我能够想到的最简单的可证明示例.

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

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


Con*_*ion 6

因为当它可以很容易地用语言本身实现时,你不应该将某些东西作为语言特性来实现.记忆功能属于库,这正是大多数语言所使用的.

  • 你可以通过虚拟表等在C中实现面向对象的编程,但这并不妨碍C++的创建...... (8认同)

mik*_*iku 5

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

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

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

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