2013-02-16 85 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