Elixir宏和bind_quoted [英] Elixir macros and bind_quoted

查看:111
本文介绍了Elixir宏和bind_quoted的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个宏定义了这样的模块.

I have a macro that defines a module like so.

defmodule Bar do
  def bar do
    IO.puts "I am #{inspect __MODULE__}"
  end
end

defmodule MacroFun do

  defmacro define_module(name) do
    quote do
      defmodule unquote(name) do
        import Bar
        def foo do
          bar
          IO.puts "I am #{inspect __MODULE__}"
        end
      end
    end
  end

end

defmodule Runner do
  require MacroFun

  def run do
    MacroFun.define_module Foo
    Foo.foo
  end

end

Runner.run

运行此命令的输出是:

I am Bar
I am Runner.Foo

这有道理;在Runner.run中调用了MacroFun.define_module,因此模块被定义并嵌套在Runner模块下.

Which makes sense; MacroFun.define_module was called in Runner.run so the module was defined and thus nested under the Runner module.

但是现在如果我将MacroFun.define_module更改为使用:bind_quoted选项:

But now if I change MacroFun.define_module to use the :bind_quoted option:

  defmacro define_module(name) do
    quote bind_quoted: [name: name] do
      defmodule name do
        import Bar
        def foo do
          bar
          IO.puts "I am #{inspect __MODULE__}"
        end
      end
    end
  end

现在输出变为:

I am Bar
I am Foo

为什么?

推荐答案

我认为这是因为您取消引用(绑定)变量name的位置其中.

I think that's because the place where you are unquoting (binding) the variable name.

在第一种情况下,在创建模块时未引用变量name,因此此时绑定变量将需要检查上下文(例如,检查代码是否在另一个模块内部).因此,您将获得当前的原子以及相应的上下文:Runner.Foo.

In the first case, you are unquoting the variable name when creating a module, thus binding the variable at that moment would require to check for context (check if the code is inside another module, for example). So, you get your current atom plus the appropriate context: Runner.Foo.

在第二种情况下,您要在变量name放入上下文之前将其取消引用,因此其值不会改变,它将是原子Foo(无上下文).

In the second case, you are unquoting the variable name before it's placed in a context, therefore its value will not change and it'll be the atom Foo (no context).

这篇关于Elixir宏和bind_quoted的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆