Reputation: 1
I am trying to create multiple processes in Erlang. For each key in the map, I want to create a process.
I have tried using the fold operation. Below is the code snippet for the same:
CreateMultipleThreads = fun(Key,Value,ok) ->
Pid = spawn(calculator, init_method, [Key,Value,self()])
end,
maps:fold(CreateMultiplThreads,[],Map).
When maps:fold(CreateMultiplThreads,[],Map)
is executed, the program terminates with the following error :
init terminating in do_boot.
Upvotes: 0
Views: 204
Reputation: 48589
init terminating in do_boot
Searching around for similar errors, it looks like that error could be caused by improper command line arguments or your file name conflicts with an erlang file name. Therefore, you would need to post how you are running your program.
Below is a working example that you might be able to adapt to your situation--including how to run it:
calculator.erl:
-module(calculator).
-compile(export_all).
init(X, Y, Pid) ->
io:format("init() in Process ~w got args ~w, ~w, ~w~n",
[self(), X, Y, Pid]).
my.erl:
-module(my).
-compile([export_all]).
go() ->
FoldFunc = fun(Key, Value, Acc) ->
Pid = spawn(calculator, init, [Key, Value, self()]),
[Pid|Acc] % Returns new value for Acc
end,
Map = #{a => 3, b => 7, c => 10},
_Pids = maps:fold(FoldFunc, [], Map). % [] is the initial value for Acc.
When you call a fold
function, e.g. lists:foldl()
, lists:foldr()
, maps:fold()
, you iterate over each value in a collection, like a list or map, and perform some operation with each value, then you accumulate the results of those operations, and the fold function returns the accumulated results.
In the shell:
~/erlang_programs$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3 (abort with ^G)
1> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}
2> c(calculator).
calculator.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,calculator}
3> Calculators = my:go().
init() in Process <0.80.0> got args a, 3, <0.64.0>
init() in Process <0.81.0> got args b, 7, <0.64.0>
init() in Process <0.82.0> got args c, 10, <0.64.0>
[<0.82.0>,<0.81.0>,<0.80.0>] %Return value of my:go()
4>
The reason you might want to accumulate the pids of the spawned processes is to receive messages that are tagged with the pids of the spawned processes. For instance, if you want to get results from each of the calculators, you might use a receive clause like this:
Pid = % One of the calculator pids
receive
{Pid, Result} ->
%Do something with result
where each calculator does this:
Pid ! {self(), Result}
Something like this:
calculator.erl:
-module(calculator).
-compile(export_all).
init(X, Y, Pid) ->
io:format("init() in Process ~w got args ~w, ~w, ~w~n",
[self(), X, Y, Pid]),
RandNum = rand:uniform(5), % time it takes to perform calc
timer:sleep(RandNum * 1000), % sleep 1-5 seconds
Pid ! {self(), RandNum}. % send back some result
my.erl:
-module(my).
-compile([export_all]).
go() ->
FoldFunc = fun(Key, Value, Acc) ->
Pid = spawn(calculator, init, [Key, Value, self()]),
[Pid|Acc]
end,
Map = #{a => 3, b => 7, c => 10},
Calculators = maps:fold(FoldFunc, [], Map),
lists:foreach(fun(Calculator) ->
receive
{Calculator, Result} ->
io:format("Result from ~w is: ~w~n", [Calculator, Result])
end
end,
Calculators
).
In the shell:
7> c(calculator).
calculator.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,calculator}
8> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}
9> my:go().
init() in Process <0.107.0> got args a, 3, <0.64.0>
init() in Process <0.108.0> got args b, 7, <0.64.0>
init() in Process <0.109.0> got args c, 10, <0.64.0>
Result from <0.109.0> is: 5
Result from <0.108.0> is: 4
Result from <0.107.0> is: 3
ok
Upvotes: 0
Reputation: 91825
init terminating in do_boot
is not your problem. This just means that something caused your node to fail to start. Erlang has a habit of printing out lots of error messages. Your actual error is probably a few lines (or even lots of lines) above this. Look there first.
With that said, I tried your code directly in the erl
shell:
$ erl
1> CreateMultipleThreads =fun(Key,Value,ok)-> Pid = spawn(calculator, init_method, [Key,Value,self()]) end.
#Fun<erl_eval.18.128620087>
2> Map = #{k1 => v1, k2 => v2}.
#{k1 => v1,k2 => v2}
3> maps:fold(CreateMultipleThreads,[],Map).
** exception error: no function clause matching erl_eval:'-inside-an-interpreted-fun-'(k1,v1,[])
in function erl_eval:eval_fun/6 (erl_eval.erl, line 829)
in call from maps:fold_1/3 (maps.erl, line 257)
What this is trying to tell you is that the function that you passed to maps:fold
doesn't match the expected form -- no function clause matching <mangled-name> (k1,v1,[])
.
It's attempting to pass (k1, v1, [])
, but your function is expecting (Key, Value, ok)
. The []
doesn't match the ok
.
Where did the []
come from? It came from the accumulator value you initially passed to maps:fold
. On each iteration, the previous result is passed as the new accumulator, so you need to think about how to keep it all matching.
If you genuinely don't want the result, just pass ok
as the initial accumulator value, match ok
, and make sure to return ok
:
CreateMultipleThreads = fun(Key, Value, ok) ->
Pid = spawn(calculator, init_method, [Key, Value, self()]),
ok
end.
maps:fold(CreateMultipleThreads, ok, Map).
Or you can do something useful with the accumulator, such as collect the process IDs:
Map = #{k1 => v1, k2 => v2},
CreateMultipleThreads = fun(Key, Value, Acc)->
Pid = spawn(calculator, init_method, [Key, Value, self()])
[Pid | Acc]
end,
Pids = maps:fold(CreateMultipleThreads, [], Map),
Pids.
Obviously, I can't actually test this, because calculator:init_method/3
doesn't exist for me, but you get the idea, hopefully.
Upvotes: 2