Current section
Files
Jump to
Current section
Files
lib/operator.ex
defmodule Operator do
@moduledoc ~S"""
Helpers for defining operator aliases for functions
Operators can be hard to follow, especially with the limited number available
in Elixir. Always having a named function backing an operator makes it easy to
fall back to the named version. Named fall backs are also very useful for
piping (`|>`).
## Examples
defmodule Example do
use Operator
@doc "Divide two numbers"
@operator a ~> b
def divide(a, b), do: a / b
@doc "Multiply two numbers"
@operator a <~> b
def multiply(a, b), do: a * b
end
import Example
divide(10, 5)
#=> 5
10 ~> 2
#=> 5
multiply(10, 2)
#=> 20
10 <~> 2
#=> 20
"""
defmacro __using__(_) do
quote do
import Kernel, except: [def: 2]
require unquote(__MODULE__)
import unquote(__MODULE__)
end
end
@doc ~S"""
Modified `def` that applies the most recent `@operator`
## Examples
@operator x <~> y
# ...
def add(a, b), do: a + b
add(1, 2)
#=> 3
1 <~> 2
#=> 3
"""
@spec def(any, nil | any) :: any
defmacro def(call, expr \\ nil) do
quote do
if @operator, do: defalias(call, as: @operator)
Kernel.def(call, expr)
@operator nil # Unset @operator
end
end
@doc ~S"""
Define an operator alias for a named function
## Examples
defalias(max, a <|> b)
10 <|> 8
#=> 10
"""
@spec defalias(atom, as: any) :: any
defmacro defalias(fun_name, as: op_expression) do
quote do
defdelegate unquote(op_expression), to: __MODULE__, as: unquote(fun_name)
end
end
end