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