How To Do A For Loop In Elixir (using only recursion)

I think it would be something like this:

defmodule For do
    # Create a closure which contains a function that applies itself to itself.
    # Call this function with as argument a function that calls the passed function with the passed `arg`.
    # In lambda calculus: `Y = λf.(λx.f(x x))(λx.f(x x))`
    # An easier definition: `Y f = f (Y f)`
    # If there exist at least one 'fixed point' where the function `f` does not call the passed function, this structure terminates.
    # 
    # This `y_combinator/0` can be called with a double anonymous function: 
    #   The outermost receives the fixpoint function as input, which can be called when you want to recurse.
    #   The innermost receives whatever argument needs to be passed during iterations.
  def y_combinator do
   fn f -> 
      (fn x -> 
        x.(x) 
      end).(
        fn y -> 
          f.(
            fn arg -> 
              y.(y).(arg) 
            end
          ) 
        end
      ) 
    end
  end

  def loop(initialization, condition, body) do
    y_combinator.(fn recurse ->
      fn state ->
        if !condition.(state) do 
          state
        else
          state
          |> body.()
          |> recurse.()
        end
      end
    end).(initialization)
  end
end

Which could then be called as follows:

For.loop(0, &(&1 <= 10), fn i -> 
  IO.puts(i)
  i + 1
end)

I wonder if this could be made even more ‘idiomatic imperative programming-like’ when doing something with (unhygienic) macros.

6 Likes