消息传递时 Erlang 处理 "badarg" 错误

Erlang handling "badarg" error when message passing

我是 Erlang 的新手,我试图通过消息传递将从一个函数获得的结果传递给另一个函数,但我不确定为什么当我执行 ie main 时它会给我 badarg 错误! {数字,1,100}。我已尝试进行一些更改,如灰色部分所示,但使用 From 时消息未通过。这是我的代码:

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

如果你从main ! Message得到一个badarg,这意味着没有进程注册在名称main下。它要么没有开始,要么一开始就没有正确注册,或者在某个时候已经死了。您可以添加更多打印语句来跟踪发生的情况。

您可以使用erlang:registered/2查看注册的内容。

执行此功能:

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

将启动一个名为 main 的进程,该进程执行函数 numbers:main/2。函数numbers:main/2开始执行后,进入接收子句等待消息。

如果您随后执行函数proc/0,它也会进入接收子句并等待消息。如果你向进程 运行 proc/0 发送一条消息,例如 {work, 1, 3},那么 proc/0 将向 numbers:main/2 发送一条消息,例如 {return, 6}numbers:main/2 将显示一些输出。证明如下:

~/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> 

如您所见,没有 badarg 错误。当你声称发生了什么事时,你需要用证据来支持它——仅仅说发生了什么事是不够的。

当您向 main 发送第一条消息时,它由带有消息 {numbers,1,100} 的接收语句处理,在此语句中,您生成了两次 proc() 函数,并终止了接收语句。

因此,主进程终止,不再注册,一旦 proc 函数尝试在第 main ! {return, Res}, 行发送消息,您就会收到 badarg 错误。

您需要像在第 main(Total+Result, N-1) 行那样递归调用主函数,以使主进程保持活动状态。 (参见 RichardC 的回答)