【问题标题】:Pattern matching of exception names异常名称的模式匹配
【发布时间】:2016-08-10 06:26:45
【问题描述】:

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

【问题讨论】:

    标签: elixir


    【解决方案1】:

    在前面的示例中,生成的异常主要是文本,括号中包含 (ArithmeticError)。

    异常不是文本,只是 iex 正在打印异常的文本表示,而不是确切的值 (source)。这是确切的例外:

    iex(1)> try do
    ...(1)>   :math.sqrt(-1)
    ...(1)> rescue
    ...(1)>   e -> e
    ...(1)> end
    %ArithmeticError{message: "bad argument in arithmetic expression"}
    

    这是一个结构体ArithmeticError,带有message 字段,如Kernel.SpecialForms.try/1 的文档中所述:

    救援条款

    除了依赖模式匹配之外,rescue 子句还为异常提供了一些便利,允许人们通过名称来拯救异常。

    【讨论】:

    • [. . .] allows one to rescue an exception by its name:所以这很方便。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2017-06-29
    • 2021-05-13
    • 1970-01-01
    • 2018-05-09
    • 2010-11-05
    • 2021-09-28
    • 2017-11-02
    • 1970-01-01
    相关资源
    最近更新 更多