Erlang记忆化的简单示例

Erlang记忆化的简单示例,erlang,Erlang,假设您有一个简单的函数,对于较大的值,它可能会非常昂贵: fact(0) -> 1; fact(N) -> N * fact(N - 1). 在哪里可以找到使用dets缓存(或记忆)函数值的简单示例 任何其他便于记忆的方法都将受到高度赞赏。这个想法是,每次你要求进行繁重的计算时,如果你已经对其进行了评估,就立即检查缓存。如果是,只需返回存储的值。如果没有,则必须在将新值返回给最终用户之前计算并存储它 一个,而不是一个dets表,也可以工作 (以下解决方案未经测试) 您可能希望将整个

假设您有一个简单的函数,对于较大的值,它可能会非常昂贵:

fact(0) -> 1;
fact(N) -> N * fact(N - 1).
在哪里可以找到使用
dets
缓存(或记忆)函数值的简单示例


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

这个想法是,每次你要求进行繁重的计算时,如果你已经对其进行了评估,就立即检查缓存。如果是,只需返回存储的值。如果没有,则必须在将新值返回给最终用户之前计算并存储它

一个,而不是一个dets表,也可以工作

(以下解决方案未经测试)

您可能希望将整个内容封装到一个文档中。在init函数中,您应该创建DETS表,fact/1函数应该表示您的API,并且您应该在handle_调用函数中实现逻辑

一个更好的例子是为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.

显然,即使这对大数有帮助,也必须考虑为每一步添加查找表中的条目的额外成本。考虑到引入缓存的原因(我们假设计算非常繁重,因此查找插入时间无关紧要),这应该很好。

根据您的情况,您还可以使用用于记忆:

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.

回忆录不是打字错误。看,哈哈。很抱歉:D你总是学到一些新东西:P这个例子的要点是,如果你有12个!记住,你算13!将该值乘以13。但是,您的代码将计算13!从一开始,不管是什么,我都知道。我想应该选择存储所有的部分值,或者只存储最终值。我对“回忆录”一无所知。该示例只是想使用dets显示“缓存”。即使只存储最终值,这些也将是下一次计算的部分结果。我只是想指出,您也应该检查do_fact函数中的缓存值。您也可以使用ets模块,而不是dets或dict模块:我一直在大量使用它解决动态编程类型的问题。我希望它与其他实现记忆化的方法相比是有效的。。i、 例如,希望get和put是一些散列中的O(1)操作。
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.