11

所以我开始学习 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]

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

4

3 回答 3

17

最终返回值是如何构造的...

第一次返回时[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

代码是如何工作的...

在 functionimportant/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,低},{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.

在外壳中运行它:

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}]
于 2012-06-11T00:46:07.023 回答
4

他们在这里连接

[Msg | important()]

important()是一个函数,所以它有一个返回值,当你在 REPL 中运行它时,他会打印函数的返回值。该值是[Head | Tail]列表构建的效果import()

important()这是一个常规功能:)

有帮助吗?

于 2012-06-10T20:09:49.010 回答
2

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

请注意,一旦normal/0被调用,就不会再对高优先级消息进行特殊处理,因为important/0它再也不会被调用。也important/0只会处理已经在队列中的高优先级消息,因为一旦它找不到任何更多然后它调用normal/0

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

于 2012-06-11T00:44:04.547 回答