Why function runs in loop when there is not a for loop

This is called a recursion. In short function calls itself as long as there is no call and therefore the result of expression at the end of function is returned. Elixir using a pattern-matching is doing a recursion based on input data. When it reach a specific function clause the algorithm finishes.

Let’s show it on simpler example:

defmodule Example do
  # here we check if input is integer and then if it's less than 0
  # if so we are using a recursive call with integer decreased by 1
  def sample(integer) when is_integer(integer) and integer > 0, do: sample(integer - 1)

  # here we check if input is integer and then if it's more than 0
  # if so we are using a recursive call with integer increased by 1
  def sample(integer) when is_integer(integer) and integer < 0, do: sample(integer + 1)

  # here we have a literal check, it works as same as
  # def sample(integer) when is_integer(integer) and integer == 0, do: :done
  # so if we enter 0 as argument or the argument in recursion call is decreased/increased to 0
  # then we return done atom
  def sample(0), do: :done
end

iex> Example.sample(-5)
:done

iex> Example.sample(0)
:done

iex> Example.sample(5)
:done