I am trying to start a simple process that will loop and receive addition or subtraction commands to calculate them. However when I register my process I try to print it with a whereis() to see if it is up and running and it returns undefined. Any idea what is going wrong?
-module(math).
-export([start/0, math/0]).
start() -> register(myprocess, spawn(math, math(), [])).
math() ->
io:format("~p~n", [whereis(myprocess)]),
receive
{add, X, Y} ->
io:format("~p + ~p = ~p~n", [X,Y,X+Y]),
math();
{sub, X, Y} ->
io:format("~p - ~p = ~p~n", [X,Y,X-Y]),
math()
end.
Here is my input in the erl shell as well:
Eshell V12.0 (abort with ^G)
1> c(math).
{ok,math}
2> math:start().
undefined
Remove the parens on the math() parameter passed to spawn.
The second parameter to spawn is supposed to be the atom for the name of the process, but you're actually invoking the function and passing the result to spawn (all of which has to happen before register itself is called).
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.
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.
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
Why receive expression is sometimes called selective receive?
What is the "save queue"?
How the after section works?
There is a special "save queue" involved in the procedure that when you first encounter the receive expression you may ignore its presence.
Optionally, there may be an after-section in the expression that complicates the procedure a little.
The receive expression is best explained with a flowchart:
receive
pattern1 -> expressions1;
pattern2 -> expressions2;
pattern3 -> expressions3
after
Time -> expressionsTimeout
end
Why receive expression is sometimes called selective receive?
-module(my).
%-export([test/0, myand/2]).
-compile(export_all).
-include_lib("eunit/include/eunit.hrl").
start() ->
spawn(my, go, []).
go() ->
receive
{xyz, X} ->
io:format("I received X=~w~n", [X])
end.
In the erlang shell:
1> c(my).
my.erl:3: Warning: export_all flag enabled - all functions will be exported
{ok,my}
2> Pid = my:start().
<0.79.0>
3> Pid ! {hello, world}.
{hello,world}
4> Pid ! {xyz, 10}.
I received X=10
{xyz,10}
Note how there was no output for the first message that was sent, but there was output for the second message that was sent. The receive was selective: it did not receive all messages, it received only messages matching the specified pattern.
What is the "save queue"?
-module(my).
%-export([test/0, myand/2]).
-compile(export_all).
-include_lib("eunit/include/eunit.hrl").
start() ->
spawn(my, go, []).
go() ->
receive
{xyz, X} ->
io:format("I received X=~w~n", [X])
end,
io:format("What happened to the message that didn't match?"),
receive
Any ->
io:format("It was saved rather than discarded.~n"),
io:format("Here it is: ~w~n", [Any])
end.
In the erlang shell:
1> c(my).
my.erl:3: Warning: export_all flag enabled - all functions will be exported
{ok,my}
2> Pid = my:start().
<0.79.0>
3> Pid ! {hello, world}.
{hello,world}
4> Pid ! {xyz, 10}.
I received X=10
What happened to the message that didn't match?{xyz,10}
It was saved rather than discarded.
Here it is: {hello,world}
How the after section works?
-module(my).
%-export([test/0, myand/2]).
-compile(export_all).
-include_lib("eunit/include/eunit.hrl").
start() ->
spawn(my, go, []).
go() ->
receive
{xyz, X} ->
io:format("I received X=~w~n", [X])
after 10000 ->
io:format("I'm not going to wait all day for a match. Bye.")
end.
In the erlang shell:
1> c(my).
my.erl:3: Warning: export_all flag enabled - all functions will be exported
{ok,my}
2> Pid = my:start().
<0.79.0>
3> Pid ! {hello, world}.
{hello,world}
I'm not going to wait all day. Bye.4>
Another example:
-module(my).
%-export([test/0, myand/2]).
-compile(export_all).
-include_lib("eunit/include/eunit.hrl").
sleep(X) ->
receive
after X * 1000 ->
io:format("I just slept for ~w seconds.~n", [X])
end.
In the erlang shell:
1> c(my).
my.erl:3: Warning: export_all flag enabled - all functions will be exported
{ok,my}
2> my:sleep(5).
I just slept for 5 seconds.
ok
In Erlang I am creating 2 processes linked to each other. If I exit form one process then the other ignores it, if exited normally. This behaviour can be seen documented in a link.
My Question is, on compiling the same code twice I can see the second process also got exit. Here are my sample code:
-module(exitnormal).
-export([f1/0]).
f1() ->
X = whereis(f2) =/= undefined,
if
X -> exit( whereis(f2), shutdown ), timer:sleep(1);
true -> ""
end,
register( f2, spawn_link( fun() -> f2() end )),
receive
kill -> { ok, f1 }
end.
f2() ->
receive
kill -> { ok, f2 }
end.
and I ran it with the following results:
1> c(exitnormal).
{ok,exitnormal}
2> erlang:register( f1, spawn( exitnormal, f1, [] )).
true
3> whereis(f2) ! kill, ok.
ok
4> whereis(f2).
undefined
5> whereis(f1).
<0.40.0>
6> c(exitnormal).
{ok,exitnormal}
7> whereis(f1).
<0.40.0>
8> c(exitnormal).
{ok,exitnormal}
9> whereis(f1).
undefined
10> erlang:register( f1, spawn( exitnormal, f1, [] )).
true
11> whereis(f1) ! kill, ok.
ok
12> whereis(f1).
undefined
13> whereis(f2).
<0.59.0>
14> c(exitnormal).
{ok,exitnormal}
15> c(exitnormal).
{ok,exitnormal}
16> whereis(f2).
undefined
17>
As described in the Compilation and Code Loading section of the Erlang Reference Manual, a module can have two variants in a running system: "current" and "old". When you reload a module, the new version becomes the "current" one, the one that was previously "current" becomes "old", and the one that was previously "old" is purged. When the old version is purged, any process that still uses it, or has references to funs from the old version, is killed. That's why your processes are killed after reloading the code twice.
This happens even if the module hasn't changed between the two loads; the act of loading will unconditionally trigger the transition.
I am trying to inspect the messages a node receives from other nodes, but in some other manner other than flush(), because the message size is rather big and it doesn't help. Also, I can see the messages with erlang:process_info(self(), messages_queue_len)., but I would like some way of extracting one message at a time in some kind of variable for debugging purposes.
You might want to have a look to the dbg module in Erlang.
Start the tracer:
dbg:tracer().
Trace all messages received (r) by a process (in this case self()):
dbg:p(self(), r).
More information here.
or you can use:
1> F = fun() -> receive X -> {message, X} after 0 -> no_message end end.
#Fun<erl_eval.20.111823515>
2> F().
no_message
3> self() ! foo.
foo
4> self() ! bar.
bar
5> F().
{message, foo}
6> F().
{message, bar}
... to prevent blocking
receive is the erlang primitive for taking messages from the mailbox.
See: http://www.erlang.org/doc/getting_started/conc_prog.html#id2263965
If you just want to get the first message in the shell for debugging, you could try defining a fun like this:
1> self() ! foo.
foo
2> F = fun() -> receive X -> X end end.
#Fun<erl_eval.20.67289768>
3> F().
foo