保護條款的基本用法

在 Elixir 中,可以建立具有相同名稱的函式的多個實現,並指定在呼叫函式之前將應用於函式的引數的規則,以便確定要執行的實現。

這些規則由關鍵字 when 標記,它們位於函式定義中的 def function_name(params)do 之間。一個簡單的例子:

defmodule Math do

  def is_even(num) when num === 1 do
    false
  end
  def is_even(num) when num === 2 do
    true
  end

  def is_odd(num) when num === 1 do
    true
  end
  def is_odd(num) when num === 2 do
    false
  end

end

假設我用這個例子執行 Math.is_even(2)is_even 有兩種實現方式,具有不同的保護條款。系統將按順序檢視它們,並執行引數滿足 guard 子句的第一個實現。第一個指定 num === 1 不是真的,所以它移動到下一個。第二個指定 num === 2,這是真的,所以這是使用的實現,返回值將是 true

如果我執行 Math.is_odd(1) 怎麼辦?系統檢視第一個實現,並看到由於 num1,第一個實現的保護條款得到滿足。然後它將使用該實現並返回 true,而不是在檢視任何其他實現。

警衛在他們可以執行的操作型別方面受到限制。 Elixir 文件列出了每個允許的操作 ; 簡而言之,它們允許比較,數學,二元運算,型別檢查(例如 is_atom)和一些小的便利功能(例如 length)。可以定義自定義保護子句,但它需要建立巨集,最好留給更高階的指南。

請注意,警衛不會丟擲錯誤; 它們被視為保護條款的正常故障,系統繼續檢視下一個實現。如果你發現在呼叫帶有 params 的保護函式時你得到了什麼,那麼你期望它可能會起作用,那麼你期望工作的一個保護條款就是丟擲一個被誤吞的錯誤。

要自己看一下這個,建立然後呼叫一個沒有意義的保護函式,例如這個試圖除以零的函式:

defmodule BadMath do
  def `divide(a)` when a / 0 === :foo do
    :bar
  end
end

呼叫 BadMath.divide("anything") 將提供有點無益的錯誤 (FunctionClauseError) no function clause matching in BadMath.divide/1 - 而如果你試圖直接執行 "anything" / 0,你會得到一個更有用的錯誤:(ArithmeticError) bad argument in arithmetic expression