エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

Elixirのドキュメントでガードをグルーピングするときの覚書

ドキュメントを生成した時に、defguard で定義するガードをグルーピングするときの設定について、いつも忘れてしまい自分の以前のリポジトリを見返すことがたびたびなので、こちらの覚書として記録しておきます。

ガードと関数をモジュールに記述した場合、

defmodule FizzBuzz do
  defguard is_pos_integer(n) when is_integer(n) and n > 0
  defguard is_fizz(n) when is_pos_integer(n) and rem(n, 3) == 0
  defguard is_buzz(n) when is_pos_integer(n) and rem(n, 5) == 0

  def fizz_buzz(n) when is_fizz(n) and is_buzz(n), do: "Fizz Buzz"
  def fizz_buzz(n) when is_fizz(n), do: "Fizz"
  def fizz_buzz(n) when is_buzz(n), do: "Buzz"
  def fizz_buzz(n) when is_pos_integer(n), do: to_string(n)
end

何も指定せず ExDoc でドキュメントを生成すると、ガードも Functions にまとめられます。

ドキュメントを紐解くと、@doc 属性と :groups_for_functions を指定することで関数を任意のグループにグルーピングできると書かれています。

hexdocs.pm

ドキュメントにはガードへの言及はないのですが、defguard の実装を確認してみると、@doc guard: true のの設定が確認できます。

結論として、mix.exs で次のように :groups_for_functions を指定すると、ガードを独立したグループにグルーピングすることができるようになります。

defmodule FizzBuzz.MixProject do
  use Mix.Project

  def project do
    [
      app: :fizz_buzz,
      version: "0.1.0",
      elixir: "~> 1.13",
      start_permanent: Mix.env() == :prod,
      deps: deps(),
      docs: docs() # 追加
    ]
  end

  # ...中略...

  # 追加
  defp docs do
    [
      groups_for_functions: [
        Guards: & &1[:guard]
      ]
    ]
  end
end