# Loops
You can iterate over lists, tuples, keyword lists, and maps in a few different ways. Here are the most common ones:
## The `for/1` Comprehension
```elixir
# You can iterate over a range ascending
result = for idx <- 1..10//1, do: idx
IO.inspect(result, label: "range - asc")
# Or descending. Note the step of -2.
# If you don't set the step, the loop will stop after the first element.
result = for idx <- 10..1//-2, do: idx
IO.inspect(result, label: "range - desc")
# You can iterate through a list of elements
result = for el <- ["Peter", 32, 190.47, :active], do: el
IO.inspect(result, label: "elements")
# Or you can have a nested for-loop
result = for x <- [1, 2], y <- [4, 5], do: [x: x, y: y]
IO.inspect(result, label: "nested")
```
<!-- livebook:{"output":true} -->
```
range - asc: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
range - desc: [10, 8, 6, 4, 2]
elements: ["Peter", 32, 190.47, :active]
nested: [[x: 1, y: 4], [x: 1, y: 5], [x: 2, y: 4], [x: 2, y: 5]]
```
## `Enum` helpers
You will mostly use the `Enum` helper functions to iterate and modify collections. Here are the most used ones:
```elixir
# Apply a function to every element and return the result.
Enum.map([1, 2, 3], fn x -> x * 2 end)
# => [2, 4, 6]
# Apply a function, but ignore the result.
Enum.each([1, 2, 3], fn x -> x * 2 end)
# => :ok
# Apply a function and add the result to an accumulator.
Enum.reduce([1, 2, 3], 0, fn x, acc -> acc + x end)
# => 6
# Only keep the elements for which the function evaluates to truthy and filter out the rest.
Enum.filter([1, 2, 3], fn x -> x == 2 end)
# => [2]
# Reject/remove an element if the function evaluates to truthy.
Enum.reject([1, 2, 3], fn x -> x == 2 end)
# => [1, 3]
```
## Recursive Functions
A common pattern in functional programming is to have recursive loops using function clauses. Elixir uses [tail call optimisation](https://en.wikipedia.org/wiki/Tail_call) to keep the memory overhead low and to avoid stack overflows.
```elixir
defmodule RunElixir.Loop do
def loop(collection, fun), do: do_loop(collection, [], fun)
# Applies an anonymous function to each element and returns the result as list.
defp do_loop([], result, _fun), do: Enum.reverse(result)
defp do_loop([value | rest], result, fun), do: do_loop(rest, [fun.(value) | result], fun)
end
RunElixir.Loop.loop([1, 2, 3], &(&1 * 2))
# => [2, 4, 6]
```
Our `loop/2` function executes the `do_loop/3` private function which calls itself recursively until it has traveresed the entire list. With every call, the second clause of `do_loop/3` removes one element from the list, applies the anonymous function to it, and adds the result to the results list. When the list of elements is exhausted, the first `do_loop/3` clause matches. It reverses the results and returns them.