简体   繁体   中英

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

If you get a badarg from main ! Message 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.

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}, 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)

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.

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