为什么所有例外都不是建立在Elixir的同一模型上?

时间:2016-08-27 10:57:03

标签: elixir

在玩加载和评估文件(主要用于配置加载)时,我遇到了几种可能引发异常的错误:

  • 该文件不存在引发%Code.LoadError{file: ..., message: ...}
  • 如果配置文件中存在某种语法错误,可以得到:
    • %SyntaxError{description: ..., file: ..., line: ...}
    • TokenMissingError{description: ..., file: ..., line: ...}

不幸的是,这些例外(xxxError s)并非使用相同的参数构建:错误描述有时会使用密钥description,有时会使用密钥message。我发现这很烦人,因为需要检查所有可能使代码冗长的问题,并且永远不能确定对于某些其他类型的错误,不会使用其他密钥。

我想知道是否有某些原因和/或是否在未来的版本中通过选择一个或另一个密钥来解决这个问题(总是很棘手,因为更改会引入向后不兼容性)。

1 个答案:

答案 0 :(得分:1)

所有这些都有一些共同之处:它们都实现了Exception行为。访问Exception消息的正确方法是将其传递给Exception.message/1(而不是exception.message)。 Exception可以包含任何字段(它们只是结构)(请查看Kernel.Macros.defexception/1),这是您使用IO.inspect打印时看到的内容。它们可能包含也可能不包含message字段,但在传递给Exception.message/1时始终会返回消息。以下是您提到的所有3个错误的示例:

defmodule Main do
  defmacro go(do: block) do
    quote do
      try do
        unquote(block)
      rescue
        e -> e
      end
    end
  end

  def main do
    e1 = go(do: Code.load_file("foo"))
    e2 = go(do: Code.string_to_quoted!("do: end"))
    e3 = go(do: Code.string_to_quoted!("do"))
    for e <- [e1, e2, e3] do
      IO.inspect {e.__struct__, Exception.message(e)}
    end
  end
end

Main.main

输出:

{Code.LoadError, "could not load /private/tmp/foo"}
{SyntaxError, "nofile:1: unexpected token: end"}
{TokenMissingError,
 "nofile:1: missing terminator: end (for \"do\" starting at line 1)"}