【问题标题】:Simple example for Erlang memoizationErlang 记忆的简单示例
【发布时间】:2010-07-22 20:33:40
【问题描述】:

假设你有一个简单的函数,它对于大值会变得相当昂贵:

fact(0) -> 1;
fact(N) -> N * fact(N - 1).

在哪里可以找到使用dets 缓存(或记忆)函数值的简单示例?

任何其他便于记忆的方式都将受到高度赞赏。

【问题讨论】:

标签: erlang


【解决方案1】:

根据您的情况,您还可以使用process dictionary 进行记忆:

fact(0) -> 1;
fact(N) ->
    case erlang:get({'fact', N}) of
        F when is_integer(F) ->
            F;
        'undefined' ->
            F = N * fact(N-1),
            erlang:put({'fact', N}, F),
            F
    end.

【讨论】:

  • 我一直在大量使用它来解决动态编程类型的问题。我希望它比其他实现记忆的方法更有效。即,希望 get 和 put 是 O(1) 操作到一些哈希中。
【解决方案2】:

这个想法是,每次您要求进行 heavy 计算时,如果您已经评估过它,您会立即检查缓存。如果是,您只需返回存储的值。如果没有,您必须评估新值并存储它,然后再将其返回给最终用户。

dict,而不是 dets 表,也可以工作。

(以下方案未经测试)

-module(cache_fact).

-export([init/0, fact/1]).

init() ->
    {ok, _} = dets:open_file(values, []).

fact(N) ->
    case dets:lookup(values, N) of
      [] ->
        Result = do_fact(N), 
        dets:insert_new(values, {N, Result}),
        Result;
      [{N, Cached}] ->
        Cached
    end.

do_fact(0) ->
    1;
do_fact(N) ->
    N * do_fact(N-1).

您可能希望将整个内容封装到 Erlang generic server 中。在 init 函数中你应该创建 DETS 表,fact/1 函数应该代表你的 API,你应该在 handle_call 函数中实现逻辑。

一个更好的例子是为 URL 编写一个缩短服务,缓存。

正如@Zed 所建议的,存储部分结果以避免进一步的重新计算是有意义的。如果是这样的话:

-module(cache_fact).

-export([init/0, fact/1]).

init() ->
    {ok, _} = dets:open_file(values, []).

fact(0) ->
    1;
fact(N) ->
    case dets:lookup(values, N) of
      [] ->
        Result = N * fact(N-1),
        dets:insert_new(values, {N, Result}),
        Result;
      [{N, Cached}] ->
        Cached
    end.

显然,即使这对大数字有帮助,您也必须考虑为每个步骤添加一个条目到查找表的额外成本。考虑到引入缓存的原因(我们假设计算量很大,所以查找插入时间并不重要),这应该是完全可以的。

【讨论】:

  • 这个例子的重点是,如果你有 12 个!记住了,你算13!通过将该值乘以 13。但是您的代码将计算 13!从一开始,不管记住什么。
  • 我知道。我想选择是存储所有部分值或仅存储最终值。我对“记忆”完全陌生。该示例只是想使用 dets 显示“缓存”。
  • 即使您只存储最终值,这些也将是您下次计算的部分结果。我只是想指出,您也应该在 do_fact 函数中检查缓存值。
  • 除了 dets 或 dict 模块,您还可以使用 ets 模块:erlang.org/doc/man/ets.html
猜你喜欢
  • 2014-03-24
  • 1970-01-01
  • 2011-10-12
  • 2013-02-08
  • 2014-12-19
  • 2013-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多