我在Erlang中遇到了编码问题,这可能是一种常见的设计模式,但我找不到任何有关如何解决它的信息。
我有一个列表L.我想将函数f应用于L中的每个元素,并让它同时运行在L中的所有元素中。每次调用f(元素)都会成功或失败;在大多数情况下,它会失败,但偶尔它会成功获得L内的特定元素。
如果/当af(元素)成功,我想返回“成功”和终止对L中其他元素的f的所有调用 - 第一个“成功”是我感兴趣的全部另一方面,如果f(Element)对L中的每个元素都失败,那么我想返回“fail”。
作为一个简单的例子,假设L是一个整数列表,如果L中的元素是3,则F返回{success},或者对于任何其他值,则返回{fail}。如果L中有3个,我希望尽快找到;我不在乎有多少3s,只是至少有3个存在与否。 f可能看起来像这样:
f(Int) ->
case Int of
3 -> {success};
_ -> {fail}
end.
如何遍历Int列表以查明列表是否包含至少一个3,并尽快返回?
当然这是一种常见的功能设计模式,我只是没有在Google中使用正确的搜索字词...
答案 0 :(得分:4)
基本上有两种不同的方法。编写自己的函数,迭代返回true
或false
的列表,具体取决于是否找到3:
contains_3([3|_]) -> true;
contains_3([_|T]) -> contains_3(T);
contains_3([]) -> false.
第二个是使用已经定义的函数来进行实际迭代,直到对list元素的测试为真并为其提供测试。 lists:any
会返回true
或false
,具体取决于测试是否对至少一个元素成功:
contains_3(List) -> lists:any(fun (E) -> E =:= 3 end, List).
会做同样的事情。你选择哪一个取决于你。第二个可能更接近设计模式,但我觉得即使你使用它,你应该知道它是如何在内部工作的。在这种情况下,它是微不足道的,非常接近明确的情况。
这是一件很常见的事情,但它是否会被归类为我不知道的设计模式。它似乎是如此基本,在某种意义上“微不足道”,我会毫不犹豫地将其称为设计模式。
答案 1 :(得分:3)
自从我做了任何erlang以来已经有一段时间了,所以我不会尝试为你提供语法,但是erlang和OTP都有等待你的解决方案。
产生一个代表该功能的过程;让它遍历列表,产生尽可能多的进程,让您觉得适当地执行有效的每元素计算。
将每个进程链接到函数进程,并在返回第一个结果后让函数进程终止。
让erlang / otp清理剩余的进程。
答案 2 :(得分:2)
正如已经回答的那样,您的解决方案是使用列表:any / 2。
看到你想要它的并发版本:
any(F, List) ->
Parent = self(),
Pid = spawn(fun() -> spawner(Parent, F, List) end),
receive {Pid, Result} -> Result
end,
Result.
spawner(Parent, F, List) ->
Spawner = self(),
S = spawn_link(fun() -> wait_for_result(Spawner, Parent, length(List)) end),
[spawn_link(fun() -> run(S, F) end) || X <- List],
receive after infinity -> ok end.
wait_for_result(Spawner, Parent, 0) ->
Parent ! {Spawner, false},
exit(have_result);
wait_for_result(Spawner, Parent, Children) ->
receive
true -> Parent ! {Spawner, true}, exit(have_result);
false -> wait_for_result(Spawner, Parent, Children -1)
end.
run(S, F) ->
case catch(F()) of
true -> S ! true;
_ -> S ! false
end.
请注意,当“wait_for_children”进程执行退出(has_result)时,所有子进程(“运行”进程)将会死亡。
完全未经测试......啊,到底是什么。我会做一个例子:
4> play:any(fun(A) -> A == a end, [b,b,b,b,b,b,b,b]).
false
5> play:any(fun(A) -> A == a end, [b,b,b,b,b,b,a,b]).
true
可能仍然存在错误(可能存在错误)。
答案 3 :(得分:0)
您可能希望查看plists
模块:http://code.google.com/p/plists/虽然我不知道plists:any
是否处理
(a)在收到的第1个{success}上,告诉其他子流程停止处理&amp;尽快退出