如何在erlang中遇到特定条件时打破循环流程控制?

4

我想在Erlang编程语言中对列表进行搜索。 由于Erlang没有循环结构,我们使用递归方法来实现循环。 然而,我想知道如何打破这个循环? 比如说,一旦我们在列表中找到了所需的元素。 就像在C语言中使用break一样。

3个回答

7
Elem = 3
List = [1,2,3,4,5,6]

elem_in_list(_Elem, []) -> false;
elem_in_list(Elem, [Elem | _Rest]) -> true;
elem_in_list(Elem, [_Head | Rest]) -> elem_in_list(Elem, Rest).

在上面的代码中,我们正在给定的 List 中查找 3。如果我们展开这个过程,它看起来会像这样。
elem_in_list(3, [ 1 | [2,3,4,5,6]]) % Matches [_Head | Rest]
elem_in_list(3, [ 2 | [3,4,5,6]]) % Matches [_Head | Rest]
elem_in_list(3, [ 3 | [4,5,6]]) % Matches [Elem | _Rest]
true

0

Justin的答案是正确的。你只需要在那时停止递归。 但有时你不是自己编写递归,而是想要从内部函数(比如fold中的函数)中退出。这就是为什么Erlang有一个非局部返回关键字(即:throw)。 让我给你展示:

假设你想使用高阶函数在列表中找到最小的正整数。你可以编写以下函数:

min_pos_int(List) ->
  lists:foldl(
    fun (Int, Min) when is_integer(Int), Int > 0, Int < Min -> Int
      ; (_, Min) -> Min
    end, infinity, List).

那个方法可以行得通,但是你知道最小的可能的正整数是什么(即1)。因此,如果你的列表中有1作为元素,你可以在那里停止,对吧? 好的。在 Erlang 中,你可以通过 catchthrow 实现这一点,就像这样...
min_pos_int(List) ->
  catch lists:foldl(
    fun (1, _) -> throw(1)
      ; (Int, Min) when is_integer(Int), Int > 0, Int < Min -> Int
      ; (_, Min) -> Min
    end, infinity, List).

您也可以使用try...catch...语法来实现此功能。

min_pos_int(List) ->
  try lists:foldl(
    fun (1, _) -> throw(1)
      ; (Int, Min) when is_integer(Int), Int > 0, Int < Min -> Int
      ; (_, Min) -> Min
    end, infinity, List)
  catch EarlyResult -> EarlyResult
  end.

您可以通过执行以下操作来检查它是否有效...

1> c(my_mod), timer:tc(my_mod, min_pos_int, [L]). % with catch & throw
{1,1}
2> c(my_mod), timer:tc(my_mod, min_pos_int, [L]). % without them
{2837520,1}
3> c(my_mod), timer:tc(my_mod, min_pos_int, [L]). % with try...catch
{7,1}

0

您可以通过几种方法实现搜索,但如果您需要在列表中查找第一个匹配项,可以尝试使用带有以下条件的列表生成器:

1> [X || X <- [1, 2, 3, 4, 5], X =:= 3].
[3]

所以,我想你可以尝试在一些case块中使用它,例如:

case [X || X <- [1, 2, 3, 4, 5], X =:= 3] of
  [_] -> find;
  []  -> not_found
end.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接