Erlang : Breaking out of lists:foreach "loop"
I have a list of elements in Erlang, and I'm using lists:foreach to traverse through the elements in the list. Is there a way to break out of this "foreach loop" in the middle of the traversal. For eg: suppose I want to stop traver开发者_开发技巧sing the list further if I encounter a '1' in the list [2, 4, 5, 1, 2, 5]. How do I do this?
Another way to do it is to use throw
and catch
:
catch lists:foreach(
fun(1) ->
throw(found_one);
(X) ->
io:format("~p~n", [X])
end,
[2, 4, 5, 1, 2, 5]).
When run in the shell, this outputs:
2
4
5
found_one
EDIT: By popular demand, a more precise version that catches only what you want to catch:
try lists:foreach(
fun(1) ->
throw(found_one);
(X) ->
io:format("~p~n", [X])
end,
[2, 4, 5, 1, 2, 5])
catch
throw:found_one ->
found_one
end.
traverse(Liste) ->
traverse(Liste, []).
traverse([], Acc) ->
Acc;
traverse([1|_], Acc) ->
Acc;
traverse([H|T], Acc) ->
% do something useful here maybe?
traverse(T, Acc).
Of course this is very rough example.
There are many nice functions in lists module:
lists:foreach(fun(E) -> do_something(E) end,
lists:takewhile(fun(E) -> E =/= 1 end, List)).
or more effective but less nice
lists:takewhile(fun(1) -> false;
(E) -> do_something(E), true
end, List)
I meet the same problem and solve it by this way:
-module(foreach_until).
-export([foreach_until/3]).
foreach_until(Action, L, Judge) ->
lists:reverse(foreach_until(Action, L, Judge, []))
.
foreach_until(_, [], _, Result) ->
Result
;
foreach_until(Action, [H | T], Judge, Result) ->
case Judge(H) of
true -> Result;
false -> foreach_until(Action, T, Judge, [Action(H) | Result])
end
.
Below is an example explained how to use:
60> foreach_until:foreach_until(fun(X) -> X*X end, [1,2,3,4], fun(X)-> X >= 3 end).
[1,4]
lists:all?
do_something(A) ->
case A of
1 ->
false;
_ ->
true
end.
IsCompleted = lists:all(do_something(A), [2, 4, 5, 1, 2, 5]),
Will break out whenever do_something returns false and return the results in IsCompleted.
精彩评论