For in Elixir

defmodule ForExample do
  def run do
    # The most basic type, with a single condition.
    i = 1
    for _ <- Stream.repeatedly(fn -> i <= 3 end), i <= 3 do
      IO.puts(i)
      i = i + 1
    end

    # A classic initial/condition/after loop.
    Enum.each(0..2, fn j ->
      IO.puts(j)
    end)

    # Another way of accomplishing the basic "do this
    # N times" iteration is to use Enum.each with a range.
    Enum.each(0..2, fn i ->
      IO.puts("range #{i}")
    end)

    # Elixir doesn't have a direct equivalent to an infinite loop,
    # but we can use Stream.repeatedly for a similar effect.
    Stream.repeatedly(fn -> 
      IO.puts("loop")
      throw(:break)
    end)
    |> Enum.take(1)
    |> (fn _ -> :ok end).()
    
    # You can also use 'continue' logic in Elixir loops.
    Enum.each(0..5, fn n ->
      if rem(n, 2) == 0 do
        :continue
      else
        IO.puts(n)
      end
    end)
  end
end

ForExample.run()

This Elixir code demonstrates various looping constructs that are similar to the original example. Here’s a breakdown of the differences and similarities:

  1. Elixir doesn’t have a traditional for loop like many imperative languages. Instead, it uses comprehensions and Enum functions for iteration.

  2. The first loop uses a comprehension with Stream.repeatedly to mimic a condition-based loop. This is not idiomatic Elixir, but it demonstrates how you could achieve a similar effect.

  3. The “classic” loop is replaced with Enum.each and a range, which is more idiomatic in Elixir.

  4. The range-based loop is also implemented using Enum.each.

  5. Elixir doesn’t have an exact equivalent to an infinite loop, but we can use Stream.repeatedly to create a similar effect. We use throw and catch to break out of the loop.

  6. The last example uses Enum.each with a conditional to demonstrate the concept of “continue”.

To run this program, save it as for_example.exs and use:

$ elixir for_example.exs
1
2
3
0
1
2
range 0
range 1
range 2
loop
1
3
5

Elixir’s functional nature leads to different idioms for iteration compared to imperative languages. The Enum and Stream modules provide powerful tools for working with collections and sequences.