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 traversing the list further if I encounter a '1' in the list [2, 4, 5, 1, 2, 5]. How do I do this?
+7
A:
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.
jldupont
2009-11-30 14:56:10
Yes, I often find that it is easier to understand how something like lists:foreach works and then write your own version to cater for special cases. As you can see above the number of lines of code is trivial. Browsing the lists module source code will yield a lot of insight into the Erlang language and its use...
Alan Moore
2009-11-30 15:04:47
My sentiment too: once you've got comfortable with Erlang, this sort of expressiveness does wonders.
jldupont
2009-11-30 15:20:30
I wonder if this ever returns anything other than [] (not counting no matching function clause :o))
Zed
2009-11-30 17:26:27
@zed: of course it depends on what you put in the section "do something useful here maybe". "Acc" serves as "Accumulator". Come-on Zed, it's late ;-)
jldupont
2009-11-30 17:33:23
+4
A:
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.
legoscia
2009-11-30 15:42:39
Using exception throw is supposed to be "non local return" from function. Usage in this answer is valid throw usage and I don't understand why it is down-voted then.
Hynek -Pichi- Vychodil
2009-11-30 17:27:04
In Python community there is a saying "this solution isn't very *Pythonic* ". Is there an equivalent expression in the Erlang Community? ;-)
jldupont
2009-11-30 17:36:01
Exceptions should be used to indicate exceptional conditions, not for flow control
Don
2009-11-30 17:47:02
`throw` is not an exception per se. And it IS supposed to be used for flow control. Please refer to the Erlang's reference guide
gleber
2009-11-30 18:36:30
How do you handle "unexpected" exceptions? In this simple example what do you do if io:format throws something? You will have to be ready for "this kind of throw" and "that kind of throw". Just rewrite this to case catch, or try catch, and it will not be so simple anymore...
Zed
2009-11-30 19:02:09
+1
A:
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)
Hynek -Pichi- Vychodil
2009-12-02 09:59:20