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