-module(pmap). -export([pmap/2, pmap1/2]). -import(lists, [all/2, any/2, filter/2, reverse/1, reverse/2, foreach/2, map/2, member/2, sort/1]). % applies F to each element of L in a separate process, returning % F(X1),F(X2), ... etc. for L = [X1,X2,...]. pmap(F,L) -> Pid = self(), Ids = lists:map(fun (H) -> Id = make_ref(), spawn(fun () -> X = (catch F(H)), Pid ! {Id,X} end), Id end, L), lists:map(fun (Id) -> receive {Id,X} -> X end end, Ids). % This is the approach that the Erlang book uses: %% % applies F to each element of L in a separate process, returning %% % F(X1),F(X2), ... etc. for L = [X1,X2,...]. %% pmap(F, L) -> %% S = self(), %% %% make_ref() returns a unique reference %% %% we'll match on this later %% Ref = erlang:make_ref(), %% Pids = map(fun(I) -> %% spawn(fun() -> do_f(S, Ref, F, I) end) %% end, L), %% %% gather the results %% gather(Pids, Ref). %% do_f(Parent, Ref, F, I) -> %% Parent ! {self(), Ref, (catch F(I))}. % catch deals with exceptions %% gather([Pid|T], Ref) -> %% receive %% {Pid, Ref, Ret} -> [Ret|gather(T, Ref)] %% end; %% gather([], _) -> %% []. % applies F to each element of L in a separate process. The results % returned may not be in the same order as they appear in L. pmap1(F, L) -> S = self(), Ref = erlang:make_ref(), foreach(fun(I) -> spawn(fun() -> do_f1(S, Ref, F, I) end) end, L), %% gather the results gather1(length(L), Ref, []). do_f1(Parent, Ref, F, I) -> Parent ! {Ref, (catch F(I))}. gather1(0, _, L) -> L; gather1(N, Ref, L) -> receive {Ref, Ret} -> gather1(N-1, Ref, [Ret|L]) end.