For loop not taking new values on iteration

I am trying to do something like thi

Extractor.For.loop(0, &(&1 <= 10), fn i ->
  day_of_week = start_date |> Calendar.Date.day_of_week_name
  IO.inspect day_of_week
  IO.inspect start_date
  IEx.pry
  IO.inspect iterate(schedule[day_of_week], start_date, timezone)
  start_date =
    case start_date <= end_date do
      true -> start_date = start_date |> Calendar.DateTime.to_erl |> Calendar.DateTime.from_erl!(timezone, {123456, 6}) |> Calendar.DateTime.add!(86400)
      false -> end_date   
    end
  IO.inspect start_date
  i + interval
end)

But when Loop iterate again start_date value isnt updated it still the same old one? Why is it so?

NOTE FoorLoop is taken from How To Do A For Loop In Elixir (using only recursion)

1 Like

From the body of your loop its not clear to me what you are actually trying…

But from the headline of your question, I do guess, that you are trying to build an imperative loopp, which mutates some internal state from one iteration to the other.

The answer then is pretty simply: you cant! There is no mutability in elixir (well sometimes it seems as if, because of shadowing already bound names or tricky processes).

The more canonical way to do this, is to extract that into a function of its own which you call recursively and pass the changed “state” explicitely.

Your function could look like this one then:

defp do_loop(i, state \\ {0, []})
defp do_loop(0, state), do: state
defp do_loop(i, {num, list}) when rem(i, 2) == 0, do: do_loop(i - 1, {num + i, list})
defp do_loop(i, {num, list}), do: do_loop(i - 1, {num, [i|list]})
2 Likes

now how to use that loop? For example i have 2 values
starting = 1476120600
ending = 1476127800

and I want the increment to be 5

Then how can I do that?

defp do_loop(current, ending, ...) when current >= ending, do: #finished
defp do_loop(current, ending, ...) do
  # do something with ...
  do_loop(current + 5, ending, ...)
end

And you can even pass in a stepsize by adding another argument:

defp do_loop(current, ending, stepsize, ...) when current >= ending, do: #finished
defp do_loop(current, ending, stepsize, ...) do
  # do something with ...
  do_loop(current + stepsize, ending, ...)
end

Please try to keep your working state as an argument to the function, do not try to keep anythin in an Agent or Process-Dictionary. That will make it hard to test and reason about the function once it has passed a certain complexity!

4 Likes