为什么错误在错误的行?

时间:2015-04-20 11:04:10

标签: macros elixir

我正在潜入Chris McCord的Metaprogramming Elixir

我在输入一个例子时犯了拼写错误:

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

在shell中,错误是有意义的:

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

为什么编译此文件会在下一行中出错?我的拼写错误是一些有效的构造吗?

如果我删除了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
...

为什么使用unquote将错误转移到其他地方?

1 个答案:

答案 0 :(得分:3)

那是因为一旦你调用qoute/1,Elixir就会假设它是一个稍后定义的函数,并继续将代码编译为函数调用。但是,当我们尝试编译它时,我们会看到一个unquote,假设有一个外部定义的变量,并且当它没有时,一切都会崩溃。

我们无法解决这个问题,因为当我们扩展代码时会发生错误,并且恰好也会扩展quote / unquote。