Sheharyar
Sheharyar

Reputation: 75820

Check if Elixir module exports a specific function

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:

Upvotes: 10

Views: 7926

Answers (4)

O.O Samson
O.O Samson

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

Sheharyar
Sheharyar

Reputation: 75820

Building on the answer here and forum discussion here, there are a few ways to do it:


Check if Function exists for Module

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

Check if Function exists with specific arity

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

balexand
balexand

Reputation: 9665

Use Kernel.function_exported?/3 like this:

function_exported?(List, :to_string, 1)
# => true

Upvotes: 4

Aleksei Matiushkin
Aleksei Matiushkin

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 module Map 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

Related Questions