変数の型名を取得する

Elixirで変数の型名を文字列として取得する。iexインタプリタのiコマンドみたいなことがしたかった。

defmodule Typename do
  @spec get(any) :: String.t()
  def get(x) do
    dict = %{
      &is_atom/1      => "atom type",
      &is_binary/1    => "binary type",
      &is_bitstring/1 => "bitstring type",
      &is_boolean/1   => "boolean type",
      &is_float/1     => "float type",
      &is_function/1  => "function type",
      &is_integer/1   => "integer type",
      &is_list/1      => "list type",
      &is_map/1       => "map type",
      &is_number/1    => "number type",
      &is_pid/1       => "pid type",
      &is_reference/1 => "reference type",
      &is_tuple/1     => "tuple type",
    }

    typename_list = Enum.filter_map(
      dict,
      fn {pred, _} -> pred.(x) end,
      fn {_, name} -> name end)
    if Enum.empty?(typename_list) do
      "unknown type"
    else
      Enum.join(typename_list, " && ")
    end
  end
end

x = "hello"
IO.puts "x type is #{Typename.get(x)}"

出力:

x type is binary type && bitstring type