【问题标题】:Check if Elixir module exports a specific function检查 Elixir 模块是否导出特定函数
【发布时间】:2016-10-12 20:37:26
【问题描述】:

如何检查Elixir 模块是否暴露了特定的公共方法?如何检查函数是否已使用特定的arity 公开?

不起作用:

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

【问题讨论】:

    标签: elixir


    【解决方案1】:

    像这样使用Kernel.function_exported?/3

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

    【讨论】:

      【解决方案2】:

      the answer hereforum 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]
      • 这与我实际所做的非常相似。但这就是问题所在,它太长了。我喜欢内置的 erlang 解决方案。
      • 唯一需要注意的是,如果该函数还没有被调用,如果你使用Kernel.function_exported?,它不会显示为导出的也许更好Keyword.get(Map.__info__(:functions), :keys) == 1
      【解决方案3】:

      在编译时可以使用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
      

      【讨论】:

        猜你喜欢
        • 2020-06-05
        • 1970-01-01
        • 2021-12-26
        • 2020-04-03
        • 2015-08-09
        • 1970-01-01
        • 2020-08-13
        • 2010-12-05
        相关资源
        最近更新 更多