【问题标题】:Erlang variable pattern matchingErlang 变量模式匹配
【发布时间】:2013-08-15 22:06:56
【问题描述】:

我在一个简单的聊天应用程序中有一个service_echo 函数,它使用 SockJS 来实现多用户私人聊天。我为在线用户列表创建了一个 ETS 表。通过存储 SockJS 会话,我想在收到来自不同连接的消息时向该连接发送消息。

这是我的service_echo 代码。

service_echo(Conn, {recv, Data}, state) ->
    Obj = mochijson2:decode(Data),
    {struct, JsonData} = Obj,
    Name = proplists:get_value(<<"name">>, JsonData),
    A = ets:lookup(username,Name),
    io:format("~p",[Conn]),
    if
      length(A) =:= 0 ->
          ets:insert(username,{Name,Conn});
      true ->
          [{AA,BB}] = ets:lookup(username,Name),

          BB:send(Data)
    end,

     io:format("hello");

即使 Conn 和 BB 相同,Conn:send(data) 仍然会向浏览器发送有效数据,而 BB:send(Data) 什么也不做,甚至不显示错误。 由于我是 Erlang 新手,如有任何无意的错误,请见谅。

【问题讨论】:

  • 这真的是您一直在运行的代码,还是您为 StackOverflow 单独输入的?例如,您在第一行中使用了小写的“状态”,因此该函数将永远无法工作。为了帮助人们回答,请确保显示您尝试运行的确切代码。
  • StateEcho = sockjs_handler:init_state( &lt;&lt;"/echo"&gt;&gt;, fun service_echo/3, state, [{response_limit, 4096}]), 调用 service_echo 函数。这是我正在运行的代码,但 BB:send(Data) 没有发送消息。
  • 这段代码,无法编译,Var - 第 12 行 - 未绑定。正如理查德所说,有些信息是错误的。无论如何,为了能够帮助您,知道您在 BB 中存储了什么可能很有趣,因为模块 BB 中的函数 send/1 负责发送消息 - 第 13 行。
  • @Pascal 我在发布问题之前进行了一些编辑以使其变得简单。谢谢。 BB 与 Conn 相同,它是通过 websockets 的 SockJS 连接。输出的 io:format for Conn 看起来像 {&lt;0.161.0&gt;, [{peername,{{127,0,0,1},56247}}, {sockname,{{127,0,0,1},56247}}, {path,"/echo/039/62l0slqe/websocket"}, {headers,[]}]}}。令人讨厌的是 Conn:send 工作,而通过模式匹配与 Conn 相同的 BB 不工作按照康恩的工作方式工作。 BB:send() 不工作。

标签: sockets erlang pattern-matching sockjs


【解决方案1】:

首先,我建议您不要使用length(A) =:= 0 来测试列表A 是否为空;如果A 是一个很长的列表,计算它的元素会花费你很多,尽管结果实际上不会被使用。改用A =:= [],更简单更好。

我不明白你为什么说ConnBB 是一样的。这与您在此处发布的代码不同。如果Name 不在表中,则插入一个条目{Name, Conn}。否则,如果Name存在于表中并且与单个对象BB相关,则假设此BB是一个模块,并调用其中定义的send函数。

这可能是你读错了 if 的语义 --- 如果是这种情况,不要让 true 守卫混淆你,这就是 if-then-else 的写法二郎。也许你想拥有类似的东西:

    ...
    A = ets:lookup(username,Name),
    if
      A =:= [] ->
        ets:insert(username,{Name,Conn})
    end,
    [{_,BB}] = ets:lookup(username,Name),
    BB:send(Data)
    ...

甚至更好:

    ...
    A = ets:lookup(T,Name),
    if
      A =:= [] ->
        ets:insert(T,{Name,Conn}),
        BB = Conn;
      true ->
        [{_,BB}] = A
    end,
    BB:send(Data)
    ...

另一方面,我可能误解了您要执行的操作。如果是这种情况,请澄清。

【讨论】:

  • 感谢您提供更多见解。我的方法肯定缺乏效率。但问题是BB[{_,BB}]=A 出现后检索到与Conn 相同,这是一个SockJS 变量但不发送数据BB:send(data)Conn:send(Data) 有效。在 ETS 查找表中,元组的第二个元素与 Conn 实例相同。但是在模式匹配后检索时,不会像Conn 那样发送Data。我想我把这里的每个人都搞糊涂了。我很抱歉。
猜你喜欢
  • 2014-06-27
  • 2018-12-08
  • 2011-08-14
  • 2011-06-17
  • 2011-09-29
  • 2010-12-13
  • 2014-07-26
  • 2015-01-12
  • 2015-02-09
相关资源
最近更新 更多