Erlang中的可变数据结构

时间:2015-01-21 16:18:38

标签: clojure functional-programming erlang

我是功能方法的新手。 为了我的学习,我选择了两种函数式语言,Erlang和Clojure。 我试图编写简单的套接字服务器,它能够存储有关当前连接的信息。

例如,如果socket1想要向socket2发送消息,它应该发送到服务器:

"消息"到socket2

或者它可以是JSON。消息格式现在并不重要。

使用Clojure我发现了一些可变数据结构,例如Agent。在Clojure的案例中,我使用Agent作为可变数组,其中我存储了所有当前连接。 但我在Erlang中找不到类似的东西。你能帮帮我吗?

我搜索了我的问题,但我发现Erlang中没有可变数据结构。在这种情况下,我可以存储所有当前连接?

谢谢。

2 个答案:

答案 0 :(得分:5)

在深入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"

请注意,这种编程实质上是将全局状态重新引入(名义上)无状态系统。如果您在一个单元格中有两个进程getput值,那么您刚刚引入了资源争用,并且失去了函数式编程应该为您提供的许多好处。

如果我可以添加个人注释:选择一种具有严格打字规则的语言作为second函数语言会更明智。我没有学习Clojure + Erlang,而是建议组合如下: (Clojure,Scala),(Erlang,Haskell),(Scheme,* ML) 这更有可能丰富你的智力工具箱。

答案 1 :(得分:3)

您可以考虑使用Erlang Term Storage (ets) table。它是一个内存中的键值存储,允许用新条目替换现有条目。