在玩加载和评估文件(主要用于配置加载)时,我遇到了几种可能引发异常的错误:
%Code.LoadError{file: ..., message: ...}
%SyntaxError{description: ..., file: ..., line: ...}
或TokenMissingError{description: ..., file: ..., line: ...}
不幸的是,这些例外(xxxError
s)并非使用相同的参数构建:错误描述有时会使用密钥description
,有时会使用密钥message
。我发现这很烦人,因为需要检查所有可能使代码冗长的问题,并且永远不能确定对于某些其他类型的错误,不会使用其他密钥。
我想知道是否有某些原因和/或是否在未来的版本中通过选择一个或另一个密钥来解决这个问题(总是很棘手,因为更改会引入向后不兼容性)。
答案 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)"}