2013-02-16 89 views
1

我使用標準的IO函數從Learn you some Erlang修改了廚房模塊,以查看按執行順序打印出來的內容,並發現了一些非常奇怪的東西。基本上我跑了殼erlang函數調用亂序?

3> Pid = spawn(kitchen, fridge2, [[baking_soda]]). 
<0.41.0> 
4> kitchen:store(Pid, water). 
0 
2 
1 
ok 
ok 

在我看來,功能店已在存儲功能接收子句之前的功能fridge2調用0被打印出來,再經過2在打印後立即以下接收子句被執行並且1被最終打印。修改後的代碼如下。 store2函數如何調用store函數?這是否因爲並行執行?這條線在商店功能中做什麼{Pid, Msg} ->?這是一個函數調用嗎?爲什麼會打印?

-module(kitchen). 
-compile(export_all). 

start(FoodList) -> 
    spawn(?MODULE, fridge2, [FoodList]). 

store(Pid, Food) -> 
    Pid ! {self(), {store, Food}}, 
    io:format("~p~n", [0]), 
    receive     
     {Pid, Msg} -> 
      io:format("~p~n", [1]), 
      io:format("~p~n", [Msg]), 
      Msg 
    end. 

take(Pid, Food) -> 
    Pid ! {self(), {take, Food}}, 
    receive 
     {Pid, Msg} -> Msg 
    end. 

store2(Pid, Food) -> 
    Pid ! {self(), {store, Food}}, 
    receive 
     {Pid, Msg} -> Msg 
    after 3000 -> 
     timeout 
    end. 

take2(Pid, Food) -> 
    Pid ! {self(), {take, Food}}, 
    receive 
     {Pid, Msg} -> Msg 
    after 3000 -> 
     timeout 
    end. 

fridge1() -> 
    receive 
     {From, {store, _Food}} -> 
      From ! {self(), ok}, 
      fridge1(); 
     {From, {take, _Food}} -> 
      %% uh.... 
      From ! {self(), not_found}, 
      fridge1(); 
     terminate -> 
      ok 
    end. 

fridge2(FoodList) -> 
    receive 
     {From, {store, Food}} -> 
      From ! {self(), ok}, 
      io:format("~p~n", [2]), 
      fridge2([Food|FoodList]); 
     {From, {take, Food}} -> 
      case lists:member(Food, FoodList) of 
       true -> 
        io:format("~p~n", [3]), 
        From ! {self(), {ok, Food}}, 
        fridge2(lists:delete(Food, FoodList)); 
       false -> 
        io:format("~p~n", [4]), 
        From ! {self(), not_found}, 
        fridge2(FoodList) 
      end; 
     terminate -> 
      ok 
    end. 

回答

1

與case語句類似,receive使用模式匹配來確定要執行的子句。 {Pid, Msg}是一個將匹配任何2元組的子句。通過你

讓我們來看看你的代碼的執行 -

Pid = spawn(kitchen, fridge2, [[baking_soda]]). 

這產生一個新的過程,執行kitchen:fridge2/1功能。該函數將阻塞,直到它收到一個消息,該消息可能是{From, {[store|take], Food}}形式的二元組或原子「終止」。

kitchen:store(Pid, water). 

與此同時,您從shell調用上述函數。它將消息{self(), {store, Food}}發送到該新進程,打印「0」,然後等待接收2元組消息。

另一個過程現在收到了一個信息,它包含了它的接收。它將消息{self(), ok}發送回發送消息的進程,打印「2」,遞歸調用自身並再次等待接收消息。

shell進程現在已收到消息並繼續執行。它打印「1」,然後打印它收到的元組的第二個元素(「ok」)。最後它返回'ok'到shell。

shell打印結果(「ok」)並顯示提示。

第二個進程仍在等待接收消息。

+0

感謝您的信息。在我發佈此主題後,我開始更多地瞭解代碼,但您更瞭解了我的理解,謝謝! – pandoragami 2013-02-16 22:52:00