lib/complex/kernel.ex

defmodule Complex.Kernel do
  @moduledoc """
  Provides operator overloading for Elixir operators.

  When you `use Complex.Kernel`, be aware that the arithmetic operators
  won't work in clause guards. For that you need to use the fully qualified
  functions (i.e.: `when Kernel.+(a, b) == 1`) instead.
  """

  # This is defined as such so that Elixir 1.12 formatters don't complain
  # and Elixir 1.13+ formatters don't remove the quotes from :"**" that
  # would make this work in Elixir <= 1.12
  @pow_atom String.to_atom("**")

  defmacro __using__(_) do
    operators = [{@pow_atom, 2}, +: 2, -: 2, /: 2, *: 2]

    quote do
      import Kernel, except: unquote(operators)
      import Complex.Kernel, only: unquote(operators)
    end
  end

  def a + b, do: Complex.add(a, b)
  def a - b, do: Complex.subtract(a, b)
  def a * b, do: Complex.multiply(a, b)
  def a / b, do: Complex.divide(a, b)

  def unquote(@pow_atom)(a, b), do: Complex.power(a, b)
end