【问题标题】:erlang function call out of order?erlang函数调用乱序?
【发布时间】:2013-02-01 15:06:13
【问题描述】:

我使用标准 IO 函数从 Learn you some Erlang 修改了厨房模块,以查看按执行顺序打印的内容,我发现了一些非常奇怪的东西。基本上我在shell中运行了以下内容

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

在我看来,函数 store 在打印出 0 之后的 store 函数中的 receive 子句之前调用了函数 freezer2,然后在打印了 2 之后,执行了接收子句并最终打印了 1。修改后的代码如下。如何从 store 函数中调用冰箱函数?这是因为以某种方式并行执行吗?这行 {Pid, Msg} -&gt; 在 store 函数中是做什么的?是函数调用吗?为什么可以打印?

-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.

【问题讨论】:

    标签: process erlang


    【解决方案1】:

    类似于 case 语句,receive 使用模式匹配来确定要执行的子句。 {Pid, Msg} 是一个匹配任何 2 元组的子句。

    让我们来看看你的代码的执行 --

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

    这会产生一个执行kitchen:fridge2/1 函数的新进程。该函数会一直阻塞,直到它接收到一个 2 元组 {From, {[store|take], Food}} 或原子“终止”的消息。

    kitchen:store(Pid, water).
    

    同时,您从 shell 调用上述函数。它将消息{self(), {store, Food}} 发送到该新进程,打印“0”,然后等待接收二元组消息。

    另一个进程现在收到了一条满足其接收要求的消息。它将消息{self(), ok} 发送回发送消息的进程,打印“2”,递归调用自身并再次等待接收消息。

    shell 进程现在已收到一条消息并继续执行。它打印“1”,然后打印它收到的元组的第二个元素(“ok”)。最后它返回 'ok' 给 shell。

    shell 打印结果(“ok”)并显示提示。

    第二个进程仍在等待接收消息。

    【讨论】:

    • 感谢您的信息。发布此主题后,我开始对代码有了更多的了解,但是您更加支持了我的理解,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2016-03-30
    • 2014-02-04
    • 2016-05-22
    • 1970-01-01
    • 2015-07-04
    • 2018-03-21
    • 2014-02-17
    • 2011-02-13
    相关资源
    最近更新 更多