Erlang中的选择性接收

tkb*_*elt 9 erlang erl

所以我开始学习Erlang,我对这段代码感到困惑.

 -module(prior).
 -compile(export_all).


    important() ->
      receive
    { Priority, Msg } when Priority > 10 ->
      [Msg | important()]
  after 0 ->
     normal()
  end.

normal() ->
  receive
    { _, Msg } -> 
      [Msg | normal()]
  after 0 ->
      []
  end.
Run Code Online (Sandbox Code Playgroud)

我正在调用代码.

    10> self() ! {15, high}, self() ! {7, low}, self() ! {1, low}, self() ! {17, high}.
    {17,high}
    11> prior:important(). 
        [high,high,low,low]
Run Code Online (Sandbox Code Playgroud)

据我所知,此代码将首先通过所有高优先级消息,然后是低优先级消息.我很困惑返回值是如何[高,高,低,低],因为我没有看到它们在哪里连接在一起.

Nin*_*ing 14

如何构建最终返回值...

[Msg | important()]第一次返回时,确定最终返回值的形式.唯一值得关注的是,我们还不知道最终返回值的所有细节.因此important(),[Msg | important()]将继续评估.以下是如何[high,high,low,low]构造最终返回值的说明.

[high | important(                      )]  <---- Defines the final form
        ---------------------------------
        [high | important(             )]   <---- Adds more details
                ------------------------
                normal(                )    <---- Adds more details
                ------------------------
                [low | normal(        )]    <---- Adds more details
                       ----------------
                       [low | normal()]     <---- Adds more details
                              --------
                              [      ]      <---- Adds more details
------------------------------------------
[high | [high | [low | [low | []]]]]
[high,high,low,low]                         <---- The final return value
Run Code Online (Sandbox Code Playgroud)

代码如何工作......

在功能上important/0,after 0简单地意思是"我不等待消息来" - 如果我的邮箱中有任何消息,我会查看它; 如果没有,我将继续(执行normal())而不是在那里等待.在邮箱中,已经有{15,高},{7,低},{1,低},{17,高}.在Erlang中,邮箱中的邮件按先来先服务顺序排队.该receive条款可能很挑剔.它扫描邮箱中的所有邮件并"选择"它所需的邮件.在我们的例子中,{15,high}{17,high}首先被选中{Priority, Msg} when Priority > 10.之后,该功能normal/0接管.和{7,低},{1,低}会按顺序处理(consed).最后,我们得到了[high,high,low,low].

修改后的版本,显示处理顺序......

我们可以稍微修改一下代码,以便使处理(consing)顺序更加明确:

-module(prior).
-compile(export_all).

important() ->
    receive
    {Priority, Msg} when Priority > 10 ->
        [{Priority, Msg} | important()] % <---- Edited
    after 0 ->
    normal()
    end.

normal() ->
    receive
    {Priority, Msg} -> % <---- Edited
        [{Priority, Msg} | normal()] % <---- Edited
    after 0 ->
        []
    end.
Run Code Online (Sandbox Code Playgroud)

在shell中运行它:

4> c(prior).
{ok, prior}
5> self() ! {15, high}, self() ! {7, low}, self() ! {1, low}, self() ! {17, high}.
{17,high}
6> prior:important().
[{15,high},{17,high},{7,low},{1,low}]
Run Code Online (Sandbox Code Playgroud)

  • 我写了OP询问的代码(我相信这是我在Learn You Some Erlang中的首选)并且我赞同这个答案. (2认同)