Elixir Language
основное использование охранных оговорок
Поиск…
основные применения защитных оговорок
В 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
, с различными предложениями охраны. Система будет смотреть на них по порядку и запускать первую реализацию, где параметры удовлетворяют условию охраны. Первый указывает, что num === 1
который не является истинным, поэтому он переходит к следующему. Второй указывает, что num === 2
, что верно, поэтому это реализация, которая используется, и возвращаемое значение будет true
.
Что делать, если я запускаю Math.is_odd(1)
? Система смотрит на первую реализацию и видит, что, поскольку num
равно 1
выполняется условие охраны первой реализации. Затем он будет использовать эту реализацию и вернет true
, и не будет интересоваться любыми другими реализациями.
Охранники ограничены в типах операций, которые они могут выполнять. В документации Elixir перечислены все разрешенные операции ; в двух словах они позволяют сравнивать, математику, двоичные операции, проверку типов (например, is_atom
) и несколько небольших удобных функций (например, length
). Можно определить пользовательские предложения охраны, но для этого требуется создание макросов, и лучше всего использовать более продвинутое руководство.
Обратите внимание, что охранники не выдают ошибок; они рассматриваются как обычные отказы в предложении охраны, и система переходит к следующей реализации. Если вы обнаружите, что вы получаете (FunctionClauseError) no function clause matching
при вызове защищенной функции с параметрами, которые вы ожидаете работать, может быть, что предложение охраны, которое вы ожидаете работать, вызывает ошибку, которая проглатывается.
Чтобы увидеть это для себя, создайте, а затем вызовите функцию с защитой, которая не имеет смысла, например, которая пытается делить на ноль:
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
напрямую, вы получили бы более полезную error: (ArithmeticError) bad argument in arithmetic expression
.