【问题标题】:Elixir - Define functions in module by metaprogrammingElixir - 通过元编程在模块中定义函数
【发布时间】:2017-03-08 02:26:45
【问题描述】:

我的模块中有三个相同的方法,它们(几乎)做同样的事情。我没有重复函数定义,而是尝试定义它们一次,以保持代码最少且对所有函数都相同。

到目前为止,我已经尝试过使用Code.eval_string

defmodule MyModule do
  Enum.each ~w(method1 method2 method3), fn method ->
    @method method

    Code.eval_string """
      def #{@method}(map) when is_map(map) do
        do_map_stuff(:#{@method}, map)
      end

      def #{@method}(arg) do
        do_other_stuff(:#{@method}, arg)
      end
    """
  end

  ## Other Methods

end

但这会抛出ArgumentError:

Compiling 1 file (.ex)
** (ArgumentError) cannot invoke def/2 outside module
    (elixir) lib/kernel.ex:4297: Kernel.assert_module_scope/3
    (elixir) lib/kernel.ex:3299: Kernel.define/4
    (elixir) expanding macro: Kernel.def/2
    nofile:1: (file)

我认为引用/取消引用可能是要走的路,但我不确定如何使用它们(我已经阅读了 Elixir 网站上的Meta Guide)。

【问题讨论】:

    标签: metaprogramming elixir


    【解决方案1】:

    这样的?

    defmodule MyModule do
      def do_map_stuff(method, arg) do
        IO.inspect([method, arg])
      end
    
      Enum.each [:method1, :method2, :method3], fn method ->
        def unquote(method)(map) when is_map(map) do
          do_map_stuff(unquote(method), map)
        end
    
        def unquote(method)(arg)  do
          do_map_stuff(unquote(method), arg)
        end
      end
    end
    

    【讨论】:

    • 我更新了它以使用更适合我的情况的原子而不是字符串(并且看起来更清晰和可读!)
    猜你喜欢
    • 1970-01-01
    • 2018-02-25
    • 2016-02-24
    • 1970-01-01
    • 1970-01-01
    • 2019-11-03
    • 2017-05-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多