设计模式?函数遍历列表以搜索第一个{success}结果

mon*_*962 5 erlang

我在Erlang中遇到了编码问题,这可能是一种常见的设计模式,但我找不到有关如何解决它的任何信息.

我有一个列表L.我想将函数f应用于L中的每个元素,并让它同时运行在L中的所有元素.每次调用f(元素)都会成功或失败; 在大多数情况下它会失败,但偶尔它会成功在L内的特定元素.

如果/当af(元素)成功时,我想返回"成功" 终止对L中其他元素的f的所有调用 - 第一个"成功"是我感兴趣的所有.另一方面,如果f(元素) )L中的每个元素都失败了,那么我想返回"失败".

作为一个简单的例子,假设L是一个整数列表,如果L中的元素是3,则F返回{success},或者对于任何其他值,则返回{fail}.如果L中有3个,我希望尽快找到; 我不在乎有多少3s,只是至少有3个存在与否.f可能看起来像这样:

f(Int) ->
  case Int of
    3 -> {success};
    _ -> {fail}
  end.
Run Code Online (Sandbox Code Playgroud)

如何遍历Int列表以查明列表是否包含至少一个3,并尽快返回?

当然这是一种常见的功能设计模式,我只是没有在Google中使用正确的搜索词......

Dan*_*una 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.
Run Code Online (Sandbox Code Playgroud)

请注意,当“wait_for_children”进程退出(have_result)时,所有子进程(“run”进程)都将死亡。

完全未经测试...啊,到底是什么。我举个例子:

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
Run Code Online (Sandbox Code Playgroud)

仍然可能存在错误(并且很可能存在)。