Given a module having two functions with the same arity, but different guard clauses, how do I (ideally) see what those clauses are, or at least that there are two functions?
defmodule Test do
def greet(name) when name == "foo" do
IO.puts("Hello, bar")
end
def greet(name), do: IO.puts("Hello, #{name}")
end
Test.__info__(:functions)
doesn't work as it only returns [greet: 1]
You can decompile the code of a module into "abstract code" and dig into that to get this info. Here's how you can get the clauses of each function in a module:
module = Test
{:ok, {^module, [abstract_code: {:raw_abstract_v1, abstract_code}]}} = :beam_lib.chunks(module, [:abstract_code])
for {:function, _, name, arity, clauses} <- abstract_code do
# Uncomment the next line to print the AST of the clauses.
# IO.inspect(clauses)
IO.inspect {name, arity, length(clauses)}
end
Output:
{:__info__, 1, 7}
{:greet, 1, 2}
Note: This is likely private API and might change in the future versions of Erlang/OTP. The output above is on Erlang/OTP 20.