Операторы
В этом документе рассматриваются операторы в 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 способен парсить предопределённый набор операторов. Нет возможности определять новые операторы (как в некоторых других языках). Однако не все операторы, которые может парсить 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.14.1/operators.html