Spec-Zone.ru › Elixir 1.7

Операторы

В этом документе рассматриваются операторы в Elixir, как они парсятся, как их можно определить и как переопределять.

Приоритет и ассоциативность операторов

Ниже приведен список всех операторов, которые может анализировать Elixir, упорядоченных по убыванию приоритета вместе с их ассоциативностью:

ОператорАссоциативность
@Унарный
.Слева направо
+ - ! ^ not ~~~ Унарный
* / Слева направо
+ - Слева направо
++ -- .. <> Справа налево
in not in Слева направо
|> <<< >>> ~>> <<~ ~> <~ <~> <|> Слева направо
< > <= >= Слева направо
== != =~ === !== Слева направо
&& &&& and Слева направо
|| ||| or Слева направо
&Унарный
=Справа налево
=>Справа налево
|Справа налево
::Справа налево
whenСправа налево
<- \\ Слева направо

Операторы сравнения

Elixir предоставляет следующие встроенные операторы сравнения:

  • == - равенство
  • === - строгое равенство
  • != - неравенство
  • !== - строгое неравенство
  • > - больше
  • < - меньше
  • >= - больше или равно
  • <= - меньше или равно

Единственное отличие между == и === заключается в том, что === строже при сравнении целых чисел и чисел с плавающей точкой:

iex> 1 == 1.0
true
iex> 1 === 1.0
false

!= и !== действуют как отрицание == и === соответственно.

Порядок терминов

В Elixir разные типы данных могут сравниваться с помощью операторов сравнения:

iex> 1 < :an_atom
true

Причина, по которой мы можем сравнивать разные типы данных, заключается в прагматизме. Алгоритмы сортировки не должны беспокоиться о разных типах данных для сортировки. Для справки, общий порядок сортировки определен ниже:

number < atom < reference < function < port < pid < tuple < map < list < bitstring

При сравнении двух чисел разных типов (число — это либо целое число, либо число с плавающей точкой) всегда происходит преобразование в тип с большей точностью, если оператор сравнения не === или !==. Число с плавающей точкой будет считаться более точным, чем целое число, за исключением случаев, когда число с плавающей точкой больше/меньше +/-9007199254740992.0, в этом случае все значимые цифры числа с плавающей точкой находятся слева от десятичной точки. Это поведение существует для того, чтобы сравнение больших чисел оставалось транзитивным.

Типы коллекций сравниваются по следующим правилам:

  • Кортежи сравниваются по размеру, а затем по элементам.
  • Карты сравниваются по размеру, а затем по ключам в порядке возрастания порядка терминов, а затем по значениям в порядке ключей. В частности, целые числа всегда считаются меньше чисел с плавающей точкой.
  • Списки сравниваются по элементам.
  • Битовые строки сравниваются по байтам, неполные байты сравниваются по битам.

Пользовательские и переопределенные операторы

Определение пользовательских операторов

Elixir может анализировать предопределенный набор операторов; это означает, что невозможно определить новые операторы (в отличие от Haskell, например). Однако не все операторы, которые может проанализировать Elixir, используются в Elixir: например, + и || используются в Elixir для сложения и булевого или, но <~> не используется (но допустим).

Для определения оператора можно использовать обычные def* конструкции (def, defp, defmacro, и так далее), но с синтаксисом, аналогичным тому, как используется оператор:

defmodule MyOperators do
  # We define ~> to return the maximum of the given two numbers,
  # and <~ to return the minimum.

  def a ~> b, do: max(a, b)
  def a <~ b, do: min(a, b)
end

Для использования вновь определенных операторов необходимо импортировать модуль, который их определяет:

iex> import MyOperators
iex> 1 ~> 2
2
iex> 1 <~ 2
1

Ниже приведена таблица всех операторов, которые может анализировать Elixir, но которые по умолчанию не используются:

  • |
  • |||
  • &&&
  • <<<
  • >>>
  • ~>>
  • <<~
  • ~>
  • <~
  • <~>
  • <|>
  • ^^^
  • ~~~

Следующие операторы используются модулем Bitwise при импорте: &&&, ^^^, <<<, >>>, |||, ~~~. Дополнительную информацию см. в документации по Bitwise.

Переопределение существующих операторов

Операторы, которые использует Elixir (например, +), могут быть определены любым модулем и использоваться вместо определенных Elixir, при условии, что они не импортированы из Kernel (который импортируется во всех местах по умолчанию). Например:

defmodule WrongMath do
  # Let's make math wrong by changing the meaning of +:
  def a + b, do: a - b
end

Теперь мы получим ошибку, если попытаемся использовать этот оператор «из коробки»:

iex> import WrongMath
iex> 1 + 2
** (CompileError) iex:11: function +/2 imported from both WrongMath and Kernel, call is ambiguous

Поэтому, как упоминалось выше, нам нужно явным образом не импортировать +/2 из Kernel:

iex> import WrongMath
iex> import Kernel, except: [+: 2]
iex> 1 + 2
-1

Заключение

Хотя можно определить неиспользуемые операторы (например, <~>) и «переопределить» предопределенные операторы (например, +), сообщество Elixir в целом не рекомендует этого делать. Пользовательские операторы могут быть очень трудно читаемыми и еще труднее понятными, так как они не имеют описательного имени, как функции. Тем не менее, некоторые конкретные случаи или языки специального доменного назначения (DSL) могут оправдать эти практики.

© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.7.4/operators.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API