Erlang 记忆的简单示例

发布于 2024-09-11 16:54:24 字数 193 浏览 4 评论 0原文

假设您有一个简单的函数,对于较大的值来说可能会变得相当昂贵:

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

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

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

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

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

Where can I find a simple example of caching (or memoizing) function values by using dets?

Any other way for easy memoization would be highly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

乱世争霸 2024-09-18 16:54:24

根据您的情况,您还可以使用 流程字典 进行记忆:

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.

Depending on your case, you can also use the process dictionary for memoization:

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.
难忘№最初的完美 2024-09-18 16:54:24

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

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 通用服务器中。在 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.

显然,即使这对大量数据有帮助,您也必须考虑为每一步向查找表添加条目的额外成本。考虑到引入缓存的原因(我们假设计算量非常大,因此查找插入时间可以忽略不计),这应该完全没问题。

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

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.

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文