Erlang记忆的简单例子 [英] Simple example for Erlang memoization

查看:110
本文介绍了Erlang记忆的简单例子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设你有一个简单的功能,对于大的值可能会变得相当昂贵:

Suppose you have a simple function, which can get quite expensive for large values:

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

在哪里可以找到使用<$ c $缓存(或记忆)功能值的简单示例c> dets ?

非常感谢任何其他方式进行简单的记忆。

Any other way for easy memoization would be highly appreciated.

推荐答案

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

The idea is that every time you ask for your heavy calculation, you immediately check in the cache if you've already evaluated it. If yes, you simply return the stored value. If not, you have to evaluate the new value and to store it, before returning it to the final user.

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

A dict, rather than a dets table, could also work.

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

(The following solution is untested)

-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通用服务器。在init函数中,应该创建DETS表,事实/ 1函数应该代表你的API,你应该在handle_call函数中实现逻辑。

You might want to encapsulate the whole thing into an Erlang generic server. In the init function you should create the DETS table, the fact/1 function should represent your API and you should implement the logic in the handle_call functions.

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

A nicer example could be writing a shortener service for URLs, cached.

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

As suggested by @Zed, it would make sense to store the partial results as well to avoid further re-calculations. If this is the case:

-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.

显然,即使这对大数量有帮助,您必须考虑添加条目的额外费用到每个步骤的查找表。考虑到缓存引入的原因(我们假设计算很重,所以查询插入时间是微不足道的),这应该是完美的。

Obviously, even if this helps for large numbers, you have to consider the additional cost of adding an entry to the lookup table for every step. Considering the reasons why the caching has been introduced (we assume the calculation is very heavy, so the lookup insertion time is insignificant), this should be perfectly fine.

这篇关于Erlang记忆的简单例子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆