从地图创建多个流程

时间:2019-06-12 16:40:29

标签: erlang

我正在尝试在Erlang中创建多个进程。我要为地图中的每个键创建一个过程。

我尝试使用折叠操作。以下是相同的代码段:

CreateMultipleThreads = fun(Key,Value,ok) ->
    Pid = spawn(calculator, init_method, [Key,Value,self()])
end,
maps:fold(CreateMultiplThreads,[],Map).

执行maps:fold(CreateMultiplThreads,[],Map)时,程序终止并出现以下错误:

init terminating in do_boot.

2 个答案:

答案 0 :(得分:2)

init terminating in do_boot不是您的问题。这仅表示某些原因导致您的节点无法启动。 Erlang有打印很多错误消息的习惯。您的实际错误可能在此上方几行(甚至很多行)。先看看那里。


话虽如此,我直接在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)

这试图告诉您的是,您传递给maps:fold的函数与预期的形式-no function clause matching <mangled-name> (k1,v1,[])不匹配。

它正在尝试传递(k1, v1, []),但是您的函数期望(Key, Value, ok)[]ok不匹配。

[]来自哪里?它来自您最初传递给maps:fold的累加器值。在每次迭代中,先前的结果将作为新的累加器传递,因此您需要考虑如何保持所有匹配。


如果您确实不希望得到结果,只需传递ok作为初始累加器值,匹配ok,并确保返回 ok

CreateMultipleThreads = fun(Key, Value, ok) ->
    Pid = spawn(calculator, init_method, [Key, Value, self()]),
    ok
end.
maps:fold(CreateMultipleThreads, ok, Map).

或者您可以对累加器进行一些有用的操作,例如收集进程ID:

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.

很显然,我无法实际测试这一点,因为calculator:init_method/3对我而言并不存在,但希望您能明白。

答案 1 :(得分:0)

init terminating in do_boot

四处寻找类似的错误,看来该错误可能是由不正确的命令行参数引起的,或者您的文件名与erlang文件名冲突。因此,您需要发布程序的运行方式。

下面是一个可行的示例,您也许可以适应您的情况-包括如何运行它:

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.

当您调用fold函数时,例如lists:foldl()lists:foldr()maps:fold(),您遍历集合中的每个值(例如列表或映射),并对每个值执行一些操作,然后累积这些操作的结果, fold函数返回累加结果。

在外壳中:

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

您可能想要累积生成的进程的pid的原因是,接收带有生成的进程的pid标记的消息。例如,如果要从每个计算器获取结果,则可以使用如下的receive子句:

Pid = % One of the calculator pids

receive
   {Pid, Result} ->
       %Do something with result

每个计算器执行此操作的地方:

Pid ! {self(), Result}

类似这样的东西:

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

在外壳中:

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