Source 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. Теперь давайте узнаем, где код и данные встречаются с анонимными функциями.
© 2012-2024 The Elixir Team
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.16.3/case-cond-and-if.html