最終的な戻り値の作成方法...
[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、高}、{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.
シェルで実行します。
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}]