我正在探索Elixir并对此表示怀疑。假设我有这样的代码:
defmodule Drop2 do
def fall_velocity(planemo, distance) do
gravity = case planemo do
:earth -> 9.8
:moon -> 1.6
:mars -> 3.71
end
:math.sqrt(2 * gravity * distance)
end
end
我将负数传递给distance
以使函数失败:
iex(8)> Drop2.fall_velocity(:earth, -20)
** (ArithmeticError) bad argument in arithmetic expression
(stdlib) :math.sqrt(-392.0)
drop2.ex:9: Drop2.fall_velocity/2
通过添加异常处理可以做得更好:
defmodule Drop2 do
def fall_velocity(planemo, distance) do
try do
gravity = case planemo do
:earth -> 9.8
:moon -> 1.6
:mars -> 3.71
end
:math.sqrt(2 * gravity * distance)
rescue
ArithmeticError -> {:error, "Distance must be non-negative number"}
CaseClauseError -> {:error, "Unknown planemo: #{planemo}"}
end
end
end
现在我们有:
iex(9)> Drop2.fall_velocity(:earth, -20)
{:error, "Distance must be non-negative number"}
很好,但我不知道模式ArithmeticError
是如何匹配的。在前面的示例中,生成的异常主要是文本,括号中包含(ArithmeticError)
。它不是Elixir中通常的模式匹配。这是怎么回事?
答案 0 :(得分:4)
在前面的示例中,生成的异常主要是文本,(ArithmeticError)包含在括号中。
异常不是文本,只是iex
正在打印异常的文本表示而不是精确值(gist example)。这是确切的例外:
iex(1)> try do
...(1)> :math.sqrt(-1)
...(1)> rescue
...(1)> e -> e
...(1)> end
%ArithmeticError{message: "bad argument in arithmetic expression"}
这是一个带有ArithmeticError
字段的结构message
,如source的文档中所述:
救援条款
除了依赖模式匹配之外,rescue子句还提供了一些便利,可以通过名称来挽救异常。