Операторы
В данном документе рассматриваются операторы в Elixir, как они парсятся, как их можно определить и как их можно переопределить.
Порядок приоритета и ассоциативность операторов
Ниже приведен список всех операторов, которые может обработать Elixir, упорядоченные по убыванию приоритета вместе с их ассоциативностью:
| Оператор | Ассоциативность |
|---|---|
@ |
Унарная |
. |
Левая |
+ - ! ^ not ~~~
|
Унарная |
** |
Левая |
* /
|
Левая |
+ -
|
Левая |
++ -- +++ --- .. <>
|
Правая |
in not in
|
Левая |
|> <<< >>> <<~ ~>> <~ ~> <~> <|>
|
Левая |
< > <= >=
|
Левая |
== != =~ === !==
|
Левая |
&& &&& and
|
Левая |
|| ||| or
|
Левая |
= |
Правая |
& |
Унарная |
=> (действительно только внутри %{}) |
Правая |
| |
Правая |
:: |
Правая |
when |
Правая |
<- \\
|
Левая |
Общие операторы
Elixir предоставляет следующие встроенные операторы, определенные как функции, которые можно переопределить:
-
+и-- унарный плюс/минус -
+,-,*и/- основные арифметические операции -
++и--- конкатенация списков и вычитание -
andи&&- строгий и нестрогий логический оператор "и" -
orи||- строгий и нестрогий логический оператор "или" -
notи!- строгий и нестрогий логический оператор "не" -
inиnot in- проверка на вхождение -
@- атрибут модуля -
..- создание диапазона -
<>- конкатенация двоичных данных -
|>- конвейер -
=~- сопоставление по тексту
Многие из них могут быть использованы в гвардах; обратитесь к списку разрешенных функций и операторов гвард.
Кроме того, есть несколько других операторов, которые Elixir парсит, но фактически не использует. См. Пользовательские и переопределенные операторы ниже для списка и рекомендаций по их использованию.
Некоторые другие операторы являются специальными формами и не могут быть переопределены:
-
^- оператор привязки -
.- оператор точки -
=- оператор сопоставления -
&- оператор захвата -
::- оператор типа
Наконец, эти операторы появляются в таблице приоритета выше, но имеют смысл только в определенных конструкциях:
-
=>- см.%{} -
when- см. Гварды -
<-- см.forиwith -
\\- см. Значения по умолчанию
Операторы сравнения
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 в целом не рекомендует использовать пользовательские операторы. Их сложно читать и ещё сложнее понимать, так как у них нет описательного имени, как у функций. Тем не менее, в некоторых специфических случаях или в пользовательских языках программирования (DSL) такие решения могут быть оправданы.
Также возможно заменить предопределённые операторы, такие как +, но это крайне не рекомендуется.
© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.13.4/operators.html