从Code.eval_quoted内部获取stacktrace

时间:2018-11-24 16:50:52

标签: elixir stack-trace

在Elixir中评估带引号的块时,是否可以获得完整的堆栈跟踪信息或查看错误在哪一行抛出?

例如,我有这个模块:

defmodule Test do
  def trySomeQuotedCode() do
    quote do
      IO.puts "line 1"
      IO.puts "line 2"
      5/0
    end
    |> evalMyQuoted
  end

  def evalMyQuoted(quoted) do
    Code.eval_quoted(quoted)
  end
end

但是如果执行它,就会看到以下内容:

stack trace until 'quoted' call

它显示存在一个ArithmeticError和一个:erlang./(5, 0),这是正确的,但没有显示引用代码中的位置。通过这个小例子,仍然很容易找到错误在代码中的位置,但是如果引用的代码更大或更高级,那么可能就不那么容易了。

因此,对于此示例,是否有可能使堆栈跟踪说明错误是在引用的零件的评估中的“第3行” 上?还是从Code.eval_quoted获取行号作为返回值?

2 个答案:

答案 0 :(得分:0)

TLDR:使用location: :keep


您可以在宏中定义quote,如下所示:

defmodule Test do
    defmacro my_quote do
        quote do
            IO.puts "line 1"
            IO.puts "line 2"
            5/0
        end
    end

    def try_quote do
        my_quote()  # Line 11
    end
end

现在致电Test.try_quote

iex(7)> Test.try_quote
line 1
line 2
** (ArithmeticError) bad argument in arithmetic expression
    test.exs:11: Test.try_quote/0

因此我们可以在引号所在的行得到提示,这更好,但还不是我们想要的。

一种解决方案可能是使用宏为我们定义一个函数,如下所示:

defmodule TestMacro do
  defmacro my_quote do
    quote do
      def my_function do
        IO.puts "line 1"
        IO.puts "line 2"
        5/0 # Line 7
      end
    end
  end
end

defmodule Test do
  import TestMacro
  my_quote # Line 15
end

现在致电Test.my_function给我们:

line 1
line 2
** (ArithmeticError) bad argument in arithmetic expression
    test.exs:15: Test.my_function/0

仍然是宏被调用的那一行!但是现在如果我们将引号定义(第3行)更改为

quote location: :keep do

我们终于得到了发生错误的确切行:

line 1
line 2
** (ArithmeticError) bad argument in arithmetic expression
    test.exs:7: Test.my_function/0

答案 1 :(得分:0)

您正在寻找的是location: :keep的调用中的Kernel.quote/2选项。