异常名称的模式匹配

时间:2016-08-10 06:26:46

标签: elixir

我正在探索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中通常的模式匹配。这是怎么回事?

1 个答案:

答案 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子句还提供了一些便利,可以通过名称来挽救异常。