如何理解Erlang的receive语句?

如何理解Erlang的receive语句?,erlang,receiver,message-handlers,Erlang,Receiver,Message Handlers,我是新来的二郎,所以请对我宽容一点 我不清楚如何在erlang中执行receive语句,例如: loop() -> receive MessageA -> handlerA(); MessageB -> handlerB() end 如果接收到消息a并执行了handlerA,那么在一段时间后,在进程的收件箱中接收到消息B,handlerB会被执行吗 我想不会,因为我看到很多代码再次递归执行receive语句: loop() ->

我是新来的二郎,所以请对我宽容一点

我不清楚如何在erlang中执行receive语句,例如:

loop() ->
   receive
       MessageA -> handlerA();
       MessageB -> handlerB()
   end
如果接收到消息a并执行了handlerA,那么在一段时间后,在进程的收件箱中接收到消息B,handlerB会被执行吗

我想不会,因为我看到很多代码再次递归执行receive语句:

loop() ->
   receive
       MessageA -> 
          handlerA(),
          loop();
       MessageB -> 
          handlerB(),
          loop()
   end
但是,如果messageA的处理程序包含另一个如下的receive语句,则会出现一个问题:

loop() ->
   receive
       MessageA -> 
          loop2(),
       MessageB -> 
          handlerB(),
          loop()
   end

 loop2() ->
   receive
      MessageC ->
          handlerC()
          loop2()
      MessageD ->
          handlerD()
          loop2()
   end
在这种情况下,是否意味着如果我输入MessageA的hander,我就永远无法处理MessageB

我该如何解决这个问题?通过将MessageB的处理程序放入loop2?这看起来不是很优雅,尤其是当存在多个级别的receive语句时


有更好的方法吗?

下面的代码意味着执行接收单个消息,因此如果要接收多个消息,则需要循环。在Erlang中实现这一点的典型方法是对自己进行跟踪

loop() ->
   receive
       MessageA -> handlerA();
       MessageB -> handlerB()
   end

在上一个示例中,看起来您有某种状态机,其中A更改为另一个状态,而B保持相同的状态。当您处于期望C和D消息的状态时,您可能无法再接收消息,这不一定是一个问题,但这取决于问题域。

以下代码表示执行接收单个消息,因此如果您希望接收多个消息,则需要循环。在Erlang中实现这一点的典型方法是对自己进行跟踪

loop() ->
   receive
       MessageA -> handlerA();
       MessageB -> handlerB()
   end
在上一个示例中,看起来您有某种状态机,其中A更改为另一个状态,而B保持相同的状态。当您处于期望C和D消息的状态时,您不再能够接收a消息并不一定是个问题,但这取决于问题域。

您得到了它

关于loop和loop2的示例,这样的实现意味着您希望在收到messageA时选择一些新行为,如果messageB稍后出现,您应该放弃它。请注意,如果您使用带有大写字母的MessageA,它将成为一个变量名,并且将匹配任何消息!。在这种情况下,这是有意义的,您应该添加一个垃圾消息子句以从队列messageB和其他意外消息中删除:

loop2() ->
   receive
      messageC ->
          handlerC(),
          loop2();
      messageD ->
          handlerD(),
          loop2();
      _ ->
          loop2()
   end.
另一种可能性是实现一种状态机,然后应该使用OTP行为gen_fsm

如果不是这样,也就是说您仍然希望捕获稍后出现的消息B,我强烈建议您保持一个循环,并在一个receive语句中处理所有可能的消息。

明白了

关于loop和loop2的示例,这样的实现意味着您希望在收到messageA时选择一些新行为,如果messageB稍后出现,您应该放弃它。请注意,如果您使用带有大写字母的MessageA,它将成为一个变量名,并且将匹配任何消息!。在这种情况下,这是有意义的,您应该添加一个垃圾消息子句以从队列messageB和其他意外消息中删除:

loop2() ->
   receive
      messageC ->
          handlerC(),
          loop2();
      messageD ->
          handlerD(),
          loop2();
      _ ->
          loop2()
   end.
另一种可能性是实现一种状态机,然后应该使用OTP行为gen_fsm


如果不是这样,也就是说您仍然希望捕获稍后出现的消息B,我强烈建议您保持单个循环,并在单个接收语句中处理所有可能的消息。

谢谢!如果在处理C和D时仍然需要B消息呢?我要在第二圈重复这个把手吗?这个循环非常冗长。谢谢!如果在处理C和D时仍然需要B消息呢?我要在第二圈重复这个把手吗?这个循环非常冗长。