【问题标题】:How to define functions based on attribute to elixir?如何根据长生不老药的属性定义函数?
【发布时间】:2016-09-01 06:24:20
【问题描述】:

假设我有一个模块 SilentDefiner。我想根据其属性为Silent 定义几个函数。让我解释一下:

defmodule Silent do
  @function_names [:a, :b, :c]

  use Definer
end

defmodule Definer do
  defmacro __using__(_) do
    quote do
      Enum.each(@function_names, fn(n) ->
        def unquote(n)() do # line 5
          IO.puts "a new method is here!"
        end
      end)
    end
  end
end

但这种方法实际上不起作用,因为我有undefined function n/0 on line 5。如何实现所需的功能?

【问题讨论】:

标签: metaprogramming elixir phoenix-framework ecto


【解决方案1】:

您需要将unquote: false 传递给Definer.__using__/1 中的quote,才能在quote 中注入unquote 片段。

defmodule Definer do
  defmacro __using__(_) do
    quote unquote: false do
      Enum.each(@function_names, fn(n) ->
        def unquote(n)() do # line 5
          IO.puts "a new method is here!"
        end
      end)
    end
  end
end

defmodule Silent do
  @function_names [:a, :b, :c]

  use Definer
end

Silent.a
Silent.b
Silent.c

打印

a new method is here!
a new method is here!
a new method is here!

Kernel.SpecialForms.quote/2 docs 中详细记录了一个类似的案例,其中还提到了如何使用bind_quoted,如果您想将一些变量注入到quote 并创建unquote 片段。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-01
    • 2018-10-30
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    相关资源
    最近更新 更多