Erlang接收循环 - 变量未绑定问题

时间:2013-04-14 20:27:58

标签: erlang variable-assignment

所以我需要编写这个函数来接收来自三个不同进程的数字并保存它们。我无法让它工作,我得到“变量未绑定”错误。

serverB2(Time, Client1, Client2, Client3) ->
    receive 
        {From, TimeClient} ->
            if 
                From == Client1 ->
                    TimeClient1 = TimeClient;
                From == Client2 ->
                    TimeClient2 = TimeClient;
                From == Client3 ->
                    TimeClient3 = TimeClient;
            end,
            serverB2(Time, Client1, Client2, Client3)
    end,
List = [Time, TimeClient1, TimeClient2, TimeClient3],
io:format("~w \n", List).

1 个答案:

答案 0 :(得分:1)

您收到变量未绑定错误,因为您的代码有三个路径,并且在每个路径中,您只会绑定一个变量TimeClient1TimeClient2TimeClient3,因此您总是有两个绑定。更糟糕的是你的代码永远不会停止。您将收到消息,然后评估if语句,然后再一次又一次地递归调用serverB2代码。收到后,您的陈述没有任何代码路径。

我会用这种方式写这个

serverB2(Time, Client1, Client2, Client3) ->
  List = [ Time
      | [ receive {Client, TimeClient} -> TimeClient end
        || Client <- [Client1, Client2, Client3]]],
  io:format("~w~n", [List]).

或以更传统的方式

serverB2(Time, Client1, Client2, Client3) ->
  List = [ Time | collect_times([Client1, Client2, Client3])],
  io:format("~w~n", [List]).

collect_times([]) -> [];
collect_times([Client|Tail]) ->
  TimeClient = receive {Client, Time} -> Time end,
  [ TimeClient | collect_times(Tail) ].

以上列表理解是如何由编译器翻译的。

我在这里使用的技巧是我按照我想要的顺序接收消息而不是它们到达邮箱的顺序。我正在使用选择性接收,因为变量Client在上面两个示例中都以接收模式绑定。有更复杂的方式来接收消息,以便它们如何到达,你应该只使用非常好的理由(例如性能)。

相关问题