作者:丫头丫头520 | 来源:互联网 | 2023-05-25 17:27
我是功能方法的新手.为了我的学习,我选择了两种函数式语言,Erlang和Clojure.我正在尝试编写简单的套接字服务器,它能够存储有关当前连接的信息.
例如,如果socket1想要向socket2发送消息,它应该发送到服务器:
对socket2的"消息".
或者它可以是JSON.消息格式现在无关紧要.
使用Clojure我发现了一些可变数据结构,如Agent.在Clojure的情况下,我使用Agent作为可变数组,我存储所有当前连接.但我在Erlang中找不到类似的东西.你能帮帮我吗?
我搜索了我的问题,但我发现Erlang中没有可变数据结构.在这种情况下,我可以存储所有当前连接?
谢谢.
1> 小智..:
在你深入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"
请注意,这种编程实质上是将全局状态重新引入(名义上)无状态系统.如果你有两个进程get
并将put
值绑定到一个单元格中,那么你刚刚引入了资源争用,并且失去了函数式编程应该给你的许多好处.
如果我可以添加个人注释:选择一种具有严格打字规则的second
语言作为您的功能语言会更明智.而不是学习Clojure + Erlang,我建议组合如:(Clojure,Scala),(Erlang,Haskell),(Scheme,*ML)更有可能丰富你的智力工具箱.