Files
n8n-openai-adapter/lib/elixir/pages/Operators.md
T
2016-09-11 18:09:22 +02:00

106 lines
4.9 KiB
Markdown

# Operators
This document covers operators in Elixir, how they are parsed, how they can be defined, and how they can be overridden.
## Operator precedence and associativity
The following is a list of all operators that Elixir is capable of parsing, ordered from higher to lower precedence, alongside their associativity:
Operator | Associativity
---------------------------------------------------------------------------------------- | -------------
`@` | Unary
`.` | Left to right
`+` `-` `!` `^` `not` `~~~` | Unary
`*` `/` | Left to right
`+` `-` | Left to right
`++` `--` `..` `<>` | Right to left
`in` | Left to right
`\|>` `<<<` `>>>` `~>>` `<<~` `~>` `<~` `<~>` `<\|>` | Left to right
`<` `>` `<=` `>=` | Left to right
`==` `!=` `=~` `===` `!==` | Left to right
`&&` `&&&` `and` | Left to right
`\|\|` `\|\|\|` `or` | Left to right
`=` | Right to left
`=>` | Right to left
`\|` | Right to left
`::` | Right to left
`when` | Right to left
`<-`, `\\` | Left to right
`&` | Unary
## Defining custom operators
Elixir is capable of parsing a predefined set of operators; this means that it's not possible to define new operators (like one could do in Haskell, for example). However, not all operators that Elixir can parse are *used* by Elixir: for example, `+` and `||` are used by Elixir for addition and boolean *or*, but `<~>` is not used (but valid).
To define an operator, you can use the usual `def*` constructs (`def`, `defp`, `defmacro`, and so on) but with a syntax similar to how the operator is used:
```elixir
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
```
To use the newly defined operators, we **have to** import the module that defines them:
```elixir
iex> import MyOperators
iex> 1 ~> 2
2
iex> 1 <~ 2
1
```
The following is a table of all the operators that Elixir is capable of parsing, but that are not used by default:
* `|`
* `|||`
* `&&&`
* `<<<`
* `>>>`
* `~>>`
* `<<~`
* `~>`
* `<~`
* `<~>`
* `<|>`
* `^^^`
* `~~~`
The following operators are used by the `Bitwise` module when imported: `&&&`, `^^^`, `<<<`, `>>>`, `|||`, `~~~`. See the documentation for `Bitwise` for more information.
## Redefining existing operators
The operators that Elixir uses (for example, `+`) can be defined by any module and used in place of the ones defined by Elixir, provided they're specifically not imported from `Kernel` (which is imported everywhere by default). For example:
```elixir
defmodule WrongMath do
# Let's make math wrong by changing the meaning of +:
def a + b, do: a - b
end
```
Now, we will get an error if we try to use this operator "out of the box":
```elixir
iex> import WrongMath
iex> 1 + 2
** (CompileError) iex:11: function +/2 imported from both WrongMath and Kernel, call is ambiguous
```
So, as mentioned above, we need to explicitly *not* import `+/2` from `Kernel`:
```elixir
iex> import WrongMath
iex> import Kernel, except: [+: 2]
iex> 1 + 2
-1
```
## Final note
While it's possible to defined unused operators (such as `<~>`) and to "override" predefined operators (such as `+`), the Elixir community generally discourages this. Custom-defined operators can be really hard to read and even more to understand, as they don't have a descriptive name like functions do. That said, some specific cases or custom domain specific languages (DSLs) may justify these practices.