A while loop macro hygiene problem

The actual warning is much more detailed:

$ elixir while.exs
warning: variable "x" is unused

Note variables defined inside case, cond, fn, if and similar do not leak. If you want to conditionally override an existing variable "x", you will have to explicitly return the variable. For example:

    if some_condition? do
      atom = :one
    else
      atom = :two
    end

should be written as

    atom =
      if some_condition? do
        :one
      else
        :two
      end

Unused variable found at:
  while.exs:27

And it turns out it has nothing to do with macros:

defmodule Test do

  def go do
    x = 7

    try do
      for _ <- Stream.cycle([:ok]) do
        if x > 4 do
          IO.puts x
          x = x - 1
        else
          throw :break
        end
      end
    catch
      :break -> :ok
    end
  end

end

has exactly the same problem. for is a list comprehension (not a “for loop”) - so I suspect that each element (:ok) of the stream creates a new closure that initializes x to its current value 7. What the compiler is warning you about is that the closure’s value of x isn’t used anywhere.

There was a discussion about a “while” loop a while back.

If you look at the examples in the book (p.25) you should notice that there is nothing in block that is driving towards the terminating condition for expression - i.e. there is nothing happening in block that changes the state expression is inspecting.

1 Like