Trying to define my own if macro

Your macro’s are calling do_my_if in the ‘callers’ scope, not the macro scope. This is proven by showing that both branches are taken:

iex> import Control
Control
iex> my_if(2==2, do: IO.inspect(true), else: IO.inspect(false))
true
false
true

You can change it to (and should, you cannot make it private because anything a defmacro calls (actually calls, not inside a quote) needs to be publicly accessible, I’m not sure why but they do) by changing your module to be:

defmodule Control do
  defmacro my_if(expr, do: if_block, else: else_block) do
    Control.do_my_if(expr, do: if_block, else: else_block)
  end

  defmacro my_if(expr, do: if_block) do
    Control.do_my_if(expr, do: if_block, else: nil)
  end

  def do_my_if(expr, do: if_block, else: else_block) do
    quote do
      case unquote(expr) do
          result when result in [false, nil] -> unquote(else_block)
          _ -> unquote(if_block)
      end
    end
  end
end

Which then results in:

iex> import Control
Control
iex> my_if(2==2, do: IO.inspect(true), else: IO.inspect(false))
true
true

:slight_smile:

I can detail ‘why’ if curious, but looking over the code and getting it to ‘click’ yourself can often be more enlightening in the tough world of macros. :slight_smile: