Current section

Files

Jump to
funx lib macros.ex
Raw

lib/macros.ex

defmodule Funx.Macros do
@moduledoc """
Provides macros for automatically implementing `Funx.Eq` and `Funx.Ord` protocols
for a given struct based on a specified field.
These macros simplify the process of defining equality and ordering behaviors
for custom structs by leveraging an existing field's comparison operations.
"""
@doc """
Generates an implementation of the `Funx.Eq` protocol for the given struct,
using the specified field as the basis for equality comparison.
## Examples
defmodule Person do
defstruct [:name, :age]
end
require Funx.Macros
Funx.Macros.eq_for(Person, :age)
iex> Eq.eq?(%Person{age: 30}, %Person{age: 30})
true
iex> Eq.eq?(%Person{age: 25}, %Person{age: 30})
false
"""
defmacro eq_for(for_struct, field) do
quote do
alias Funx.Eq
defimpl Funx.Eq, for: unquote(for_struct) do
def eq?(%unquote(for_struct){unquote(field) => v1}, %unquote(for_struct){
unquote(field) => v2
}),
do: Eq.eq?(v1, v2)
def not_eq?(%unquote(for_struct){unquote(field) => v1}, %unquote(for_struct){
unquote(field) => v2
}),
do: Eq.not_eq?(v1, v2)
end
end
end
@doc """
Generates an implementation of the `Funx.Ord` protocol for the given struct,
using the specified field as the basis for ordering comparisons.
## Examples
defmodule Person do
defstruct [:name, :age]
end
require Funx.Macros
Funx.Macros.ord_for(Person, :age)
iex> Ord.lt?(%Person{age: 25}, %Person{age: 30})
true
iex> Ord.gt?(%Person{age: 35}, %Person{age: 30})
true
"""
defmacro ord_for(for_struct, field) do
quote do
alias Funx.Ord
defimpl Funx.Ord, for: unquote(for_struct) do
def lt?(%unquote(for_struct){unquote(field) => v1}, %unquote(for_struct){
unquote(field) => v2
}),
do: Ord.lt?(v1, v2)
def le?(%unquote(for_struct){unquote(field) => v1}, %unquote(for_struct){
unquote(field) => v2
}),
do: Ord.le?(v1, v2)
def gt?(%unquote(for_struct){unquote(field) => v1}, %unquote(for_struct){
unquote(field) => v2
}),
do: Ord.gt?(v1, v2)
def ge?(%unquote(for_struct){unquote(field) => v1}, %unquote(for_struct){
unquote(field) => v2
}),
do: Ord.ge?(v1, v2)
end
end
end
end