Erlang中的选择性接收

时间:2012-06-10 20:02:24

标签: 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.

我正在使用。

调用代码
    10> self() ! {15, high}, self() ! {7, low}, self() ! {1, low}, self() ! {17, high}.
    {17,high}
    11> prior:important(). 
        [high,high,low,low]

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

3 个答案:

答案 0 :(得分: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

代码的工作原理......

在功能important/0中,after 0只是表示“我不等待邮件到来” - 如果我的邮箱中有任何邮件,我会查看它;如果没有,我将继续(执行normal())而不是在那里等待。在邮箱中,已经存在 {15,high},{7,low},{1,low},{17,high} 。在Erlang中,邮箱中的邮件是以先到先得的顺序排队。 receive子句可能很挑剔。它扫描邮箱中的所有邮件并“选择”它所需的邮件。在我们的情况下, {15,high} {17,high} 首先根据{Priority, Msg} when Priority > 10选择。  之后,函数normal/0接管。 {7,low},{1,low} 按顺序处理(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.

在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}]

答案 1 :(得分:4)

他们在这里得到了结论

[Msg | important()]

这个important()是一个函数,所以它有一个返回值,而你在REPL中运行它会从函数中打印返回值。此值是[Head | Tail]

列出import()列表的效果

important()这是常规功能:)

有用吗?

答案 2 :(得分:2)

所有Erlang函数始终返回一个值。函数important/0将接收高优先级消息,然后在表达式[Msg | important()]中递归调用自身,该表达式构建包含最新Msg的列表以及important/0将包含的所有其他消息接收。这个列表是从important/0返回的。当没有更高优先级的消息时,important/0将调用normal/0来读取所有剩余的消息。 normal/0读取它的消息将以相同的方式important/0作为列表返回。这将返回到important/0,然后将其返回到返回其消息的相同列表中。

请注意,一旦调用了normal/0,就不会对高优先级消息进行特殊处理,因为important/0永远不会再被调用。此外,important/0实际上只会处理队列中已有的高优先级消息,因为它无法再找到,然后调用normal/0

超时值0的特殊之处在于它会立即超时,但保证首先搜索整个消息队列以查找匹配的消息。