【发布时间】:2016-10-12 20:37:26
【问题描述】:
如何检查Elixir 模块是否暴露了特定的公共方法?如何检查函数是否已使用特定的arity 公开?
不起作用:
Map.methodsMap.functionsMap.has_function(:keys)
【问题讨论】:
标签: elixir
如何检查Elixir 模块是否暴露了特定的公共方法?如何检查函数是否已使用特定的arity 公开?
不起作用:
Map.methodsMap.functionsMap.has_function(:keys)【问题讨论】:
标签: elixir
像这样使用Kernel.function_exported?/3:
function_exported?(List, :to_string, 1)
# => true
【讨论】:
在the answer here 和forum discussion here 的基础上,有几种方法可以做到:
您可以检查函数名称是否作为键存在于Map.__info__(:functions)
module = Map
func = :keys
Keyword.has_key?(module.__info__(:functions), func)
# => true
要检查arity,我们可以使用Kernel.function_exported?/3:
Kernel.function_exported?(Map, :keys, 1) # => true
Kernel.function_exported?(Map, :keys, 2) # => false
更新为使用内核模块中的函数,而不是 :erlang 模块
【讨论】:
module.__info__ 足以检查具有特定数量的函数:Map.__info__(:functions) |> Enum.filter(fn {k,_} -> k == :get end) [get: 2, get: 3]。
Kernel.function_exported?,它不会显示为导出的也许更好Keyword.get(Map.__info__(:functions), :keys) == 1?
在编译时可以使用Module.defines?/2:
defmodule M do
__MODULE__ |> Module.defines?({:keys, 1})
end
在运行时这将导致:
Map |> Module.defines?({:keys, 1})** (ArgumentError) 无法在模块
Map上调用defines?,因为它已经编译(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
【讨论】: