将函数同时应用于 Erlang 中元组中的每个元素
Concurrently apply function to each element in a tuple in Erlang
我有一个元组{apple, pear, orange, banana}
我还有一个功能make_juice/1
:
make_juice(apple) ->
apple_juice();
make_juice(pear) ->
pear_juice();
make_juice(orange) ->
orange_juice();
make_juice(banana) ->
banana_juice().
我想把这个函数应用到元组中的每个元素,所以我得到了结果
{apple_juice, pear_juice, orange_juice, banana_juice}
因为所有函数apple_juice/0
、pear_juice/0
、orange_juice/0
、banana_juice/0
都可能意外失败。我想申请我不希望它打断我的结果。
我想同时将函数应用于元素。在任何失败的情况下,我仍然会得到部分结果:
{apple_juice, fail, orange_juice, fail}
最简单的方法是什么?
你可以试试这段代码,它并行执行映射,同时如果有异常则将结果替换为失败
-module(juice).
-compile(export_all).
make_juice(apple) ->
apple_juice;
make_juice(pear) ->
pear_juice;
make_juice(orange) ->
orange_juice;
make_juice(banana) ->
0/0.
pmap(Function, List) ->
S = self(),
Pids = lists:map(fun(El) ->
spawn(fun() ->
execute(S, Function, El) end)
end,
List),
gather(Pids).
execute(Recv, Function, Element) ->
Recv ! {self(), Function(Element)}.
gather([]) ->
[];
gather([H|T]) ->
receive
{H, Ret} ->
[Ret|gather(T)]
end.
test() ->
Elements = [apple, banana, pear, orange],
pmap(fun(X) ->
try make_juice(X) of
Result -> Result
catch
_:_ ->
fail
end
end, Elements).
和测试:
rorra-air:~/erlang > erl
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Eshell V6.4 (abort with ^G)
1> c(juice).
juice.erl:11: Warning: this expression will fail with a 'badarith' exception
{ok,juice}
2> juice:test().
[apple_juice,fail,pear_juice,orange_juice]
3>
我有一个元组{apple, pear, orange, banana}
我还有一个功能make_juice/1
:
make_juice(apple) ->
apple_juice();
make_juice(pear) ->
pear_juice();
make_juice(orange) ->
orange_juice();
make_juice(banana) ->
banana_juice().
我想把这个函数应用到元组中的每个元素,所以我得到了结果
{apple_juice, pear_juice, orange_juice, banana_juice}
因为所有函数apple_juice/0
、pear_juice/0
、orange_juice/0
、banana_juice/0
都可能意外失败。我想申请我不希望它打断我的结果。
我想同时将函数应用于元素。在任何失败的情况下,我仍然会得到部分结果:
{apple_juice, fail, orange_juice, fail}
最简单的方法是什么?
你可以试试这段代码,它并行执行映射,同时如果有异常则将结果替换为失败
-module(juice).
-compile(export_all).
make_juice(apple) ->
apple_juice;
make_juice(pear) ->
pear_juice;
make_juice(orange) ->
orange_juice;
make_juice(banana) ->
0/0.
pmap(Function, List) ->
S = self(),
Pids = lists:map(fun(El) ->
spawn(fun() ->
execute(S, Function, El) end)
end,
List),
gather(Pids).
execute(Recv, Function, Element) ->
Recv ! {self(), Function(Element)}.
gather([]) ->
[];
gather([H|T]) ->
receive
{H, Ret} ->
[Ret|gather(T)]
end.
test() ->
Elements = [apple, banana, pear, orange],
pmap(fun(X) ->
try make_juice(X) of
Result -> Result
catch
_:_ ->
fail
end
end, Elements).
和测试:
rorra-air:~/erlang > erl
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Eshell V6.4 (abort with ^G)
1> c(juice).
juice.erl:11: Warning: this expression will fail with a 'badarith' exception
{ok,juice}
2> juice:test().
[apple_juice,fail,pear_juice,orange_juice]
3>