【问题标题】:Erlang handling "badarg" error when message passing消息传递时 Erlang 处理“badarg”错误
【发布时间】:2019-12-05 08:15:58
【问题描述】:

我是 Erlang 的新手,并试图通过消息传递将从一个函数获得的结果传递给另一个函数,但我不确定为什么当我这样做时它会给我 badarg 错误,即 main ! {数字, 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])).

【问题讨论】:

    标签: erlang


    【解决方案1】:

    如果从main ! Message得到一个badarg,则说明没有以main这个名字注册的进程。它要么没有开始或没有正确注册,要么在某个时候已经死亡。您可以添加更多打印语句来跟踪发生的情况。

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

        执行这个函数:

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

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

        如果您随后执行函数proc/0,它也会进入接收子句并等待消息。如果您向运行proc/0 的进程发送消息,例如{work, 1, 3},那么proc/0 将向{return, 6} 发送消息,例如{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 错误。当你声称某事发生时,你需要用证据来支持它——仅仅说某事发生是不够的。

        【讨论】:

          猜你喜欢
          • 2014-10-01
          • 2018-12-16
          • 1970-01-01
          • 2017-02-22
          • 1970-01-01
          • 2010-11-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多