Why is the error on the wrong line?
I'm diving into Chris McCord's Elixir Metaprogramming .
I made a spelling mistake by typing one of the 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 a shell, errors make sense:
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 does compiling this file give an error on the next line? Is my spelling mistake some valid construct?
The error is shown in the correct file if I delete 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 did the use unquote
carry over the error somewhere else?
source to share
This is because as soon as you call it qoute/1
, Elixir assumes it is a function to be defined later and proceeds to compile the code as a function call. However, when we try to compile it, we see unquote, suppose there is a variable defined externally, and everything fails when it is not.
We cannot get around this, because the error occurs when we expand the code and expand quot / unquote the same way.
source to share