[erlang-questions] Apparently strange dict behaviour

Darryn <>
Tue Aug 9 08:58:38 CEST 2011


Kind Sirs/Madams,

I'm new to erlang, but have extensive prior experience with Haskell. I thought 
I'd play with a small version of a parallel map/fold operation, but have run 
into an annoying problem. The test example is just a parallel estimation by 
sampling of Pi.

pmap(Input, MapFn) ->
    process_flag(trap_exit, true),
    spawn_workers(self(), MapFn, Input),
    M = length(Input),
    collect(M, dict:new()).

spawn_workers(Pid, Fn, Pairs) ->
    lists:foreach(fun({K1, V1}) ->
        spawn_link(fun() -> worker(Pid, Fn, {K1, V1}) end) end, Pairs).

worker(Pid, Fn, {K1, V1}) ->
    Pid ! Fn(K1, V1).

collect(0, Dict) -> Dict;
collect(N, Dict) ->
    receive
        {Key2, Val2} ->
            DictD = dict:append(Key2, Val2, Dict),                                    
%% <- problem: inserted Val2 integer apparently turns into a string?!!
            io:format("Collected result:{~p,~p}~n", [Key2, Val2]),
            io:format("    ->is_integer?~p~n", [is_integer(Val2)]),
            io:format("    ->~p~n", [dict:to_list(DictD)]),
            collect(N, DictD);
        {'EXIT', Who, Why} ->
            io:format("Worker ~p terminated with ~p~n",[Who, Why]),
            collect(N-1, Dict)
    end.

samples(Index, N) ->
    random:seed(erlang:now()),
    {Index, do_samples(0, N, 0)}.

doit() ->
    Results = pmap([{1,100}, {2,100}, {3, 100}], fun samples/2),
    dict:to_list(Results).


The problem seems to lie in the collect function, where the collected Val2 
integer (the io:format confirms it is an integer) suddenly becomes a string 
upon insertion into the dictionary. Here is example output to illustrate.

20> c(pisim).    
{ok,pisim}
21> pisim:doit().
Collected result:{1,88}
    ->is_integer?true
    ->[{1,"X"}]
Worker <0.114.0> terminated with normal
Collected result:{1,87}
    ->is_integer?true
    ->[{1,"XW"}]
Worker <0.116.0> terminated with normal
Collected result:{2,76}
    ->is_integer?true
    ->[{2,"L"},{1,"XW"}]
Worker <0.115.0> terminated with normal
[{2,"L"},{1,"XW"}]
22> c(pisim).    
{ok,pisim}
23> pisim:doit().
Worker <0.118.0> terminated with normal
Collected result:{1,78}
    ->is_integer?true
    ->[{1,"N"}]
Worker <0.123.0> terminated with normal
Collected result:{2,83}
    ->is_integer?true
    ->[{2,"S"},{1,"N"}]
Worker <0.124.0> terminated with normal
[{2,"S"},{1,"N"}]
 
I don't understand how the Val2 integer suddenly turns into a string upon 
being inserted into the dictionary; when I manually cut and paste the relevant 
bits of code into the shell I get dictionary values with integers as I intend.

I wonder if anyone more experienced can see what I've done wrong? Thanks so 
much for any help!

Darryn.



More information about the erlang-questions mailing list