檢視原始碼 case、cond 和 if

在本章節中,我們將學習 casecondif 控制流程結構。

case

case 允許我們將值與多個模式進行比較,直到找到一個匹配的模式

iex> case {1, 2, 3} do
...>   {4, 5, 6} ->
...>     "This clause won't match"
...>   {1, x, 3} ->
...>     "This clause will match and bind x to 2 in this clause"
...>   _ ->
...>     "This clause would match any value"
...> end
"This clause will match and bind x to 2 in this clause"

如果您想針對現有變數進行模式比對,則需要使用 ^ 算子

iex> x = 1
1
iex> case 10 do
...>   ^x -> "Won't match"
...>   _ -> "Will match"
...> end
"Will match"

子句也允許透過防護裝置指定額外條件

iex> case {1, 2, 3} do
...>   {1, x, 3} when x > 0 ->
...>     "Will match"
...>   _ ->
...>     "Would match, if guard condition were not satisfied"
...> end
"Will match"

僅當 x 為正數時,上面的第一個子句才會匹配。

請記住,防護裝置中的錯誤不會外洩,只會使防護裝置失敗

iex> hd(1)
** (ArgumentError) argument error
iex> case 1 do
...>   x when hd(x) -> "Won't match"
...>   x -> "Got #{x}"
...> end
"Got 1"

如果沒有子句匹配,則會引發錯誤

iex> case :ok do
...>   :error -> "Won't match"
...> end
** (CaseClauseError) no case clause matching: :ok

Kernel 模組的文件在側邊欄中列出所有可用的防護裝置。您也可以參閱完整的 模式和防護裝置 參考以取得深入的文件。

cond

當您需要針對不同的值進行比對時,case 會很有用。然而,在許多情況下,我們想要檢查不同的條件,並找到第一個不會評估為 nilfalse 的條件。在這種情況下,可以使用 cond

iex> cond do
...>   2 + 2 == 5 ->
...>     "This will not be true"
...>   2 * 2 == 3 ->
...>     "Nor this"
...>   1 + 1 == 2 ->
...>     "But this will"
...> end
"But this will"

在許多命令式語言中,這相當於 else if 子句,儘管在 Elixir 中使用頻率較低。

如果所有條件都傳回 nilfalse,則會引發錯誤 (CondClauseError)。因此,可能需要新增一個最終條件,等於 true,它將永遠匹配

iex> cond do
...>   2 + 2 == 5 ->
...>     "This is never true"
...>   2 * 2 == 3 ->
...>     "Nor this"
...>   true ->
...>     "This is always true (equivalent to else)"
...> end
"This is always true (equivalent to else)"

最後,請注意 cond 將除了 nilfalse 之外的任何值都視為 true

iex> cond do
...>   hd([1, 2, 3]) ->
...>     "1 is considered as true"
...> end
"1 is considered as true"

if/unless

除了 casecond 之外,Elixir 還提供了 if/2unless/2,當您需要只檢查一個條件時,它們會很有用

iex> if true do
...>   "This works!"
...> end
"This works!"
iex> unless true do
...>   "This will never be seen"
...> end
nil

如果提供給 if/2 的條件傳回 falsenildo-end 之間提供的內文不會執行,而會傳回 nil。使用 unless/2 時則相反。

它們也支援 else 區塊

iex> if nil do
...>   "This won't be seen"
...> else
...>   "This will"
...> end
"This will"

這也是討論 Elixir 中變數範圍的好時機。如果在 ifcase 和類似的建構中宣告或變更任何變數,宣告和變更只會在建構內可見。例如

iex> x = 1
1
iex> if true do
...>   x = x + 1
...> end
2
iex> x
1

在這些情況中,如果你要變更值,你必須從 if 傳回值

iex> x = 1
1
iex> x = if true do
...>   x + 1
...> else
...>   x
...> end
2

ifunless 是巨集

關於 if/2unless/2 的一個有趣備註是,它們在語言中實作為巨集:它們並非如許多語言中的特殊語言建構。你可以查看文件和它們的來源以取得更多資訊。

我們已經結束 Elixir 中最基本的控制流程建構的介紹。現在讓我們來學習程式碼和資料在匿名函式中相遇的地方。