Erlang - Spawn MFA vs Spawn Fun

Erlang - Spawn MFA vs Spawn Fun

我一直在尝试使用 Programming Erlang,版本 2(Joe Armstrong 的书)。我正在尝试解决第 13 章中的第一个问题。

作为问题的解决方案 - 我想到了这个 -

-module(errorhandle1).
-export([my_spawn/3,loop/1,test_func/0]).

my_spawn(Mod,Fun,Args) -> 
   %SpawnedPidRef = myspawn_helper(Mod,Fun,Args),
   %spawn(?MODULE , loop , [myspawn_helper(Mod,Fun,Args)]).
   spawn(fun() -> loop(myspawn_helper(Mod,Fun,Args)) end).

myspawn_helper(Mod,Fun,Args) ->
   statistics(wall_clock),
   spawn_monitor(Mod,Fun,Args).

loop({SpPid,SpRef}) ->
   io:format("Created Pid is : ~p~n",[SpPid]),
   receive
      {makeError,Msg} -> 
          SpPid ! Msg,
          loop({SpPid,SpRef});
      {'DOWN',SpRef, process,SpPid,Why} ->
          {_, Time1} = statistics(wall_clock),
            io:format("Down"),
            io:format("Process spawn time = ~p microsecond ~n",[Time1])
end.

test_func() ->
    receive
        X -> 
           list_to_atom(X)
    end.

以上代码有效并产生了所需的输出(第一步是解决问题)。然后我评论了这一行并提出了以下程序,它与上面的程序完全相同但是,我使用 spawn/3 函数而不是 spawn/1 并且我似乎没有得到所需的输出。

-module(errorhandle1).
-export([my_spawn/3,loop/1,test_func/0]).

my_spawn(Mod,Fun,Args) -> 
   %SpawnedPidRef = myspawn_helper(Mod,Fun,Args),
   spawn(?MODULE , loop , [myspawn_helper(Mod,Fun,Args)]).
   %spawn(fun() -> loop(myspawn_helper(Mod,Fun,Args)) end).

myspawn_helper(Mod,Fun,Args) ->
   statistics(wall_clock),
   spawn_monitor(Mod,Fun,Args).

loop({SpPid,SpRef}) ->
   io:format("Created Pid is : ~p~n",[SpPid]),
   receive
      {makeError,Msg} -> 
          SpPid ! Msg,
          loop({SpPid,SpRef});
      {'DOWN',SpRef, process,SpPid,Why} ->
          {_, Time1} = statistics(wall_clock),
            io:format("Down"),
            io:format("Process spawn time = ~p microsecond ~n",[Time1])
end.

test_func() ->
    receive
        X -> 
           list_to_atom(X)
    end.

执行上述模块的步骤: c(错误句柄 1)。 Pid = errorhandle1:my_spawn(errorhandle1,test_func,[])。 皮德! {makeError,test}.

能否请一些人帮助我理解 spawn/3 和 spawn/1 的用法?

谢谢, 萨提斯

当我 运行 你的代码时我没有看到任何问题,除了测试应该是 Pid ! {制造错误,"test"}。所以元组的第二个字段是一个列表,而不是一个原子。

spawn(fun() -> loop(myspawn_helper(Mod,Fun,Args)) end).

不等同于

spawn(?MODULE , loop , [myspawn_helper(Mod,Fun,Args)]).

在第二种情况下[myspawn_helper(Mod,Fun,Args)]是函数spawn/3的参数。在函数调用之前评估参数的值。这意味着调用 myspawn_helper(Mod,Fun,Args) 是在调用 spawn/3 之前在原始进程中的新进程之外进行的。你可以看到它是这个代码

SpawnedPidRef = myspawn_helper(Mod,Fun,Args),
spawn(?MODULE , loop , [SpawnedPidRef]).

spawn/1 的等价物看起来像

SpawnedPidRef = myspawn_helper(Mod,Fun,Args),
spawn(fun() -> loop(SpawnedPidRef) end).

现在你可以看出区别了。只有 loop(SpawnedPidRef) 实际上是在一个新进程中完成的。但是在您的第一个版本中,您在新进程中执行 loop(myspawn_helper(Mod,Fun,Args)) 。你可以这样看

spawn(fun() ->
        SpawnedPidRef = myspawn_helper(Mod,Fun,Args),
        loop(SpawnedPidRef)
    end).

这是非常不同的代码。 (见最后两块。最后一个是你的第一个版本,另一个是你的第二个版本。)