"Breaking loop" in Elixir?

Hello, I’m reading about Comprehension in Elixir, is there some function for making breaking loop ?

For example I would iterate on a list like

[1,2,3,5] 
|> Enum.each(fn x -> if x == 3, do: x end)  # I would stop the "iteration" or recursive loop when 3 is found and return 3

I found Enum.find/3 Enum — Elixir v1.12.3 who sound what I’m searching :slight_smile:

1 Like

It’s not quite clear what you actually want to accomplish. Often times you can rely on functions in the Enum module to get the behaviour you’re describing. For example, you can use Enum.any?/2 to test if a certain value in the enumerable satisfies some condition:

[1,2,3,5] 
|> Enum.any?(fn x -> x == 3 end)

But this still will only return a boolean. The fragment you posted will always return :ok. But combining Enum.any/2 with some conditional logic might lead you to the correct solution.

If you really want to implement some loop and return early (but I really don’t thing you need that, because 99% of the time there are better abstractions that do the heavy lifting for you), you can look at Enum.reduce_while/3 and friends, that allow you to halt the reduction.

2 Likes

Ok thank you I will look that :slight_smile:

Yes, you’re on the right track! After a while it becomes really fun to find the best Enum functions to solve such puzzles. The existing abstractions are really good, and there is still the more manual reduce function if you need it. If something trivial seems to take too much steps, then you’re doing it wrong :slight_smile:

This also can help: Elixir Enum Cheatsheet

5 Likes

Can you give us your real-world scenario so we can help you better?

It’s same than my example except that the numbers are maps

I would iterate on a list of elements and stop at the first element found and return this element or return nil if not element match

You may probably want Enum.reduce_while/3, or if you want to loop indefinitely Stream.unfold/1.

1 Like

Nice website thx :vulcan_salute:

Thx I will looking :wink:

Then this should suffice:

Enum.find([1, 2, 3, 5], :not_found, fn x -> x == 3 end)

And then check if :not_found is returned (that value can be anything else btw, it’s just me that picked a default to be returned if nothing is found; it can very easily be an empty map in your original scenario).

Though I also have to remark this: you asking if there’s a break construct in Elixir is a clear sign of the XY problem. Don’t ask how would we do what you think is the solution. Ask us how to achieve your initial goal.

5 Likes