简体   繁体   中英

Erlang - Spawn MFA vs Spawn Fun

I have been trying to work with Programming Erlang , Version 2 ( Joe Armstrong's book). I am trying to solve the first problem in the Chap 13.

As a solution to the problem - I came up with this -

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

The above code works and produces the desired output (first step is to solve the problem). Then I commented the line and came up with the following program , which is exactly same as the above one but , I use spawn/3 function instead of a spawn/1 and I dont seem to get the desired output.

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

Steps to execute the above module: c(errorhandle1). Pid = errorhandle1:my_spawn(errorhandle1,test_func,[]). Pid ! {makeError,test}.

Can some please help me with my understanding of the usage of spawn/3 and spawn/1 ?

Thanks, Sathish.

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

is not an equivalent of

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

in the second case [myspawn_helper(Mod,Fun,Args)] is a parameter of function spawn/3 . The value of a parameter is evaluated before a function call. It means the call myspawn_helper(Mod,Fun,Args) is made before the call to the spawn/3 outside of a new process in the original one. You can see it as this code

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

the equivalent with spawn/1 would look like

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

Now you can see the difference. Only loop(SpawnedPidRef) is actually done inside a new process. But in your first version you perform loop(myspawn_helper(Mod,Fun,Args)) in a new process. You can see it like

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

which is very different code. (See the last two blocks. The last one is you first version and other one is your second version.)

I don't see any issue when I run your code, except the test should be Pid ! {makeError,"test"}. so the second field of the tuple is a list, not an atom.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM