2016-10-12 2 views
4

Как вы можете проверить, был ли модуль Elixir опубликован конкретным общедоступным методом? Как вы проверяете, была ли функция выставлена ​​с определенным номером arity?Проверьте, не экспортирует ли модуль Elixir определенную функцию

Не работает:

  • Map.methods
  • Map.functions
  • Map.has_function(:keys)

ответ

9

Опираясь на the answer here и forum discussion here, есть несколько способов сделать это:


Проверьте функции существует для модуля

Вы можете проверить, если имя функции присутствуют в качестве ключа в Map.__info__(:functions)

module = Map 
func = :keys 

Keyword.has_key?(module.__info__(:functions), func) 
# => true 

Проверьте, если функция существует с определенной арностью

Чтобы проверить с arity, мы можем использовать :erlang.function_exported/3:

:erlang.function_exported(Map, :keys, 1)   # => true 
:erlang.function_exported(Map, :keys, 2)   # => false 
+0

'модуль .__ info__' достаточно достаточно проверить для функции с определенной арностью:' Карта .__ информации __ (Функции) |> Enum. filter (fn {k, _} -> k ==: get end) [get: 2, get: 3] '. – mudasobwa

+0

Это очень похоже на то, что я на самом деле делал. Но это проблема, она слишком длинная. Мне нравится встроенное решение erlang. – Sheharyar

0

В компиляции можно использовать Module.defines?/2:

defmodule M do 
    __MODULE__ |> Module.defines?({:keys, 1}) 
end 

Во время исполнения это приведет:

Map |> Module.defines?({:keys, 1}) 

** (ArgumentError) не могли бы назвать defines? модуль Map, потому что он был составлен

(elixir) lib/module.ex:1169: Module.assert_not_compiled!/2 
(elixir) lib/module.ex:753: Module.defines?/2 

Самый короткий вариант для выполнения будет:

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