【问题标题】:Mutable data structures in ErlangErlang 中的可变数据结构
【发布时间】:2015-03-20 06:00:10
【问题描述】:

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

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

向 socket2 发送“消息”

或者它可以是 JSON。消息格式现在无关紧要。

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

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

谢谢。

【问题讨论】:

    标签: clojure functional-programming 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"
    

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

    如果我可以添加个人说明:选择具有严格打字纪律的语言作为您的second 功能语言会更明智。我建议不要学习 Clojure+Erlang,而是建议以下组合: (Clojure, Scala), (Erlang, Haskell), (Scheme, *ML) 更有可能丰富你的智力工具箱。

    【讨论】:

    • 嗯,非常有趣的方法。非常感谢。
    【解决方案2】:

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

    【讨论】:

    • 非常感谢您提供的链接。我会试试的。
    猜你喜欢
    • 2019-03-13
    • 2012-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-20
    • 1970-01-01
    • 2014-07-10
    • 2021-07-01
    相关资源
    最近更新 更多