prostagma
prostagma

Reputation: 27

Erlang handling "badarg" error when message passing

I am new to Erlang and trying to pass the result obtained from one function to another through message passing but I am unsure why it is giving me badarg errors when I do ie main ! {numbers, 1, 100}. I have tried to make some changes, as seen in the greyed out portions, but the message didn't get passed when using From. Here is my code:

-module(numbers).
-export([start_main/0,main/2,proc/0,sumNumbers/2]).

main(Total, N) ->
  if
    N == 0 ->
      io:format("Total: ~p ~n", [Total]);
    true ->
      true
  end,
  receive
    {numbers, Low, High} ->
      Half = round(High/2),
      Pid1 = spawn(numbers, proc, []),
      Pid2 = spawn(numbers, proc, []),
      Pid1 ! {work, Low, Half},
      Pid2 ! {work, Half+1, High};
    %% Pid1 ! {work, self(), Low, Half},
    %% Pid2 ! {work, self(), Half+1, High},
    {return, Result} ->
      io:format("Received ~p ~n", [Result]),
      main(Total+Result, N-1)
  end.

proc() ->
  receive
    {work, Low, High} ->
      io:format("Processing ~p to ~p ~n", [Low, High]),
      Res = sumNumbers(Low,High),
      main ! {return, Res},
      proc()
    %%  {work, From, Low, High} ->
    %%  io:format("Processing ~p to ~p ~n", [Low, High]),
    %%  Res = sumNumbers(Low,High),
    %%  From ! {return, Res},
    %%  proc()
  end.

sumNumbers(Low, High) ->
  Lst = lists:seq(Low,High),
  lists:sum(Lst).

start_main() ->
  register(main, spawn(numbers, main, [0,2])).

Upvotes: 1

Views: 1273

Answers (3)

RichardC
RichardC

Reputation: 10567

If you get a badarg from main ! Message, it means that there is no process registered under the name main. It either didn't get started or properly registered to begin with, or it has died at some point. You can add some more print statements to follow what happens.

You can use erlang:registered/2 to see what is registered.

Upvotes: 4

7stud
7stud

Reputation: 48649

Executing this function:

start_main() ->   
    register(main, spawn(numbers, main, [0,2])).

will start a process called main, which executes the function numbers:main/2. After the function numbers:main/2 starts executing, it enters a receive clause and waits for a message.

If you then execute the function proc/0, it too will enter a receive clause and wait for a message. If you send the process running proc/0 a message, like {work, 1, 3}, then proc/0 will send a message, like {return, 6}, to numbers:main/2; and numbers:main/2 will display some output. Here's the proof:

~/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(numbers).          
{ok,numbers}

2> numbers:start_main().
true

3> Pid = spawn(numbers, proc, []).
<0.73.0>

4> Pid ! {work, 1, 3}.
Processing 1 to 3 
{work,1,3}
Received 6 

5> 

As you can see, there's no badarg error. When you claim something happens, you need to back it up with proof--merely saying that something happens is not enough.

Upvotes: 1

Pascal
Pascal

Reputation: 14042

When you send the first message to the main, it is handled by the receive statement with the message {numbers,1,100}, in this statement you spawn twice the proc() function, and terminate the receive statement.

Thus, the main process dies, it is no more registered, and as soon as the proc functions try to send their message at line main ! {return, Res}, you get the badarg error.

You need to recursively call the main function as you do it at line main(Total+Result, N-1) to keep the main process alive. (see RichardC answer)

Upvotes: 2

Related Questions