Reputation: 75820
How do you check if an Elixir
module has exposed a specific public method? How do you check if the function has been exposed with a specific arity
?
Doesn't work:
Map.methods
Map.functions
Map.has_function(:keys)
Upvotes: 10
Views: 7926
Reputation: 1
In Elixir Version > 1.14
,
Module.defines?(__MODULE__, {:version, 0}, :def) #=> true
where :version
is your function name, 0
is the arity and :def
is the kind.
see the Elixir Reference here
Upvotes: 0
Reputation: 75820
Building on the answer here and forum discussion here, there are a few ways to do it:
You can check if the function name is present as a key in Map.__info__(:functions)
module = Map
func = :keys
Keyword.has_key?(module.__info__(:functions), func)
# => true
To check with arity
, we can use Kernel.function_exported?/3
:
Kernel.function_exported?(Map, :keys, 1) # => true
Kernel.function_exported?(Map, :keys, 2) # => false
Updated to use function from the Kernel module instead of the :erlang module
Upvotes: 24
Reputation: 9665
Use Kernel.function_exported?/3
like this:
function_exported?(List, :to_string, 1)
# => true
Upvotes: 4
Reputation: 121010
In compile time one might use Module.defines?/2
:
defmodule M do
__MODULE__ |> Module.defines?({:keys, 1})
end
In runtime this will result in:
Map |> Module.defines?({:keys, 1})
** (ArgumentError) could not call
defines?
on moduleMap
because it was already compiled(elixir) lib/module.ex:1169: Module.assert_not_compiled!/2 (elixir) lib/module.ex:753: Module.defines?/2
The shortest variant for runtime would be:
iex(59)> Map.__info__(:functions)[:get]
#⇒ 2 # minimal arity, truthy
iex(60)> Map.__info__(:functions)[:nonexisting]
#⇒ nil # no such function, falsey
iex(61)> !!Map.__info__(:functions)[:get]
#⇒ true # erlang style
iex(62)> !!Map.__info__(:functions)[:nonexisting]
#⇒ false # erlang style
Upvotes: 0