在深入研究 ets 表之前,值得花点时间自己实现 ets 表之类的东西。这个想法是你启动一个进程,这个进程的状态就是你存储的数据。
下面是一个简单的存储单元类型进程示例,它可以无限期地保留一个值,也允许用户覆盖这个值。这可以很容易地扩展为在状态下保存字典,允许键+值操作。
-module(simple_storage_cell).
-export([start/0, get/1, put/2]).
start() ->
spawn_link(fun() -> loop([]) end).
get(Pid) ->
Pid ! {get, self()}, %% the self() here gets the pid of the
%% calling process, not the storage cell
receive {retrieved, Val} -> Val
after 500 -> error(timeout)
end.
put(Pid, Val) ->
Pid ! {put, self(), Val}, %% see above, in get/1
receive {saved, Val} -> Val
after 500 -> error(timeout)
end.
loop(StoredItem) ->
receive
{get, RequestingPid} ->
RequestingPid ! {retrieved, StoredItem},
%% we now 'hold' the StoredItem in the cell
loop(StoredItem);
{put, RequestingPid, NewValue} ->
RequestingPid ! {saved, NewValue},
%% we lose the old value, keeping NewValue in the cell
loop(NewValue);
OtherMsg -> error({unexpected_msg, OtherMsg})
end.
这会给你以下行为:
1> Cell = simple_storage_cell:start().
<0.33.0>
2> simple_storage_cell:get(Cell).
[]
3> simple_storage_cell:put(Cell, "hello").
"hello"
4> simple_storage_cell:get(Cell).
"hello"
5> simple_storage_cell:get(Cell).
"hello"
6> simple_storage_cell:put(Cell, "new value").
"new value"
7> simple_storage_cell:get(Cell).
"new value"
请注意,这种编程本质上是将全局状态重新引入(名义上的)无状态系统。如果您将两个进程 getting 和 puttting 值放在一个单元格中,那么您刚刚引入了资源争用,并且失去了函数式编程应该给您带来的许多好处。
如果我可以添加个人说明:选择具有严格打字纪律的语言作为您的second 功能语言会更明智。我建议不要学习 Clojure+Erlang,而是建议以下组合:
(Clojure, Scala), (Erlang, Haskell), (Scheme, *ML)
更有可能丰富你的智力工具箱。