Elixir引用/取消引用和宏行为

时间:2016-07-22 23:07:54

标签: macros elixir

我有__using__的两个版本,但是,第一个版本的行为与我预期的不同。此代码无法正常工作(实际上,它不会导入任何内容)。

defmodule SomeModule do
  defmacro __using__(opts \\ []) do
    quote do
      opts = unquote(opts)
      if Keyword.has_key?(opts, :my_key) && opts[:my_key] == 3 do
        import MyModuleOne
      else
        import MyModuleTwo
      end
    end
  end
end

这是工作版本,但是,我不喜欢有两个单独的quote部分。

defmodule SomeModule do
  defmacro __using__(opts \\ []) do
    if Keyword.has_key?(opts, :my_key) && opts[:my_key] == 3 do
      quote do
        import MyModuleOne
      end
    else
      quote do
        import MyModuleTwo
      end
    end
  end
end

如何重写第一个才能使其正常工作?

1 个答案:

答案 0 :(得分:4)

这是一个棘手的问题!花了一些时间来解决原因...

在进入原因之前,请允许我向您保证您的宏完全有效,并且Elixir的工作方式正如您告诉它

我尝试扩展您发布的两个宏并获得相同的结果,即正在导入正确的内容。但为什么它不能按预期工作?

原因如下,

  

重要的是要注意import / 2是词汇

来自import

的文档

让我给你看两个例子

iex(1)> import Enum, only: [into: 2]
Enum
iex(2)> into [a: 1], %{}
%{a: 1}
iex(3)>

和...

iex(1)> if true do
...(1)>   import Enum, only: [into: 2]
...(1)> end
Enum
iex(2)> into [a: 1], %{}
** (CompileError) iex:2: undefined function into/2

导入仅在您编写的子句中生效:)