Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the error on the wrong line?

Tags:

macros

elixir

I am diving into Metaprogramming Elixir by Chris McCord.

I made a spelling mistake while typing one of examples:

defmodule Math do
  defmacro say({:+, _, [lhs, rhs]}) do
    qoute do             #spelling mistake (swapped "o" and "u")
      lhs = unquote(lhs) #(CompileError) math.exs:4: undefined function lhs/0
      rhs = unquote(rhs)
      result = lhs + rhs
      IO.puts "#{lhs} plus #{rhs} is #{result}"
      result
    end
  end

  defmacro say({:*, _, [lhs, rhs]}) do
    qoute do #spelling mistake copied
      lhs = unquote(lhs)
      rhs = unquote(rhs)
      result = lhs * rhs
      IO.puts "#{lhs} times #{rhs} is #{result}"
      result
    end
  end
end

In the shell, the errors are meaningful:

iex(1)> qoute do: 1 + 2 #spelling mistake
** (RuntimeError) undefined function: qoute/1
iex(1)> unquote do: 1
** (CompileError) iex:1: unquote called outside quote

Why compiling this file gives error in the next line? Is my spelling mistake some valid construct?

The error appears in correct file, if I remove the unquote.

defmodule Math do
  defmacro say({:+, _, [lhs, rhs]}) do
    qoute do             #function qoute/1 undefined
      result = lhs + rhs
      IO.puts "#{lhs} plus #{rhs} is #{result}"
      result
    end
  end
...

Why using unquote moved the error somewhere else?

like image 547
tkowal Avatar asked Nov 22 '25 04:11

tkowal


1 Answers

That's because once you call qoute/1, Elixir assumes it is a function that will be defined later, and proceeds to compile the code as a function call. However, when we try to compile it, we see an unquote, assume there is a variable defined outside, and everything crashes when it doesn't.

There is no way we can work around it because the error happens when we are expanding code and is exactly when quote/unquote are expanded too.

like image 52
José Valim Avatar answered Nov 24 '25 21:11

José Valim



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!