查看源代码 case、cond 和 if
在本章中,我们将学习 case
、cond
和 if
控制流结构。
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
很有用。但是,在许多情况下,我们希望检查不同的条件并找到第一个不评估为 nil
或 false
的条件。在这种情况下,可以使用 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 中使用频率较低。
如果所有条件都返回 nil
或 false
,则会引发错误 (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
将任何除 nil
和 false
之外的值都视为真值。
iex> cond do
...> hd([1, 2, 3]) ->
...> "1 is considered as true"
...> end
"1 is considered as true"
if/unless
除了 case
和 cond
之外,Elixir 还提供 if/2
和 unless/2
,当您只需要检查一个条件时,它们很有用。
iex> if true do
...> "This works!"
...> end
"This works!"
iex> unless true do
...> "This will never be seen"
...> end
nil
如果给定给 if/2
的条件返回 false
或 nil
,则在 do
-end
之间给定的主体不会执行,而是返回 nil
。unless/2
则相反。
它们还支持 else
代码块。
iex> if nil do
...> "This won't be seen"
...> else
...> "This will"
...> end
"This will"
这也是谈论 Elixir 中变量作用域的好机会。如果在 if
、case
和类似结构中声明或更改任何变量,则声明和更改将只能在该结构中可见。例如
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
if
和unless
是宏。关于
if/2
和unless/2
的一个有趣之处是,它们在语言中被实现为宏:它们不是像在许多语言中那样是特殊的语言结构。您可以查看文档及其源代码以获取更多信息。
我们已经完成了对 Elixir 中最基本控制流结构的介绍。现在让我们学习代码和数据在匿名函数中相遇的地方。