Поиск…


основные применения защитных оговорок

В 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 .



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow