【问题标题】:Sending a keyword list to a macro and using bind_quoted将关键字列表发送到宏并使用 bind_quoted
【发布时间】:2016-10-31 13:50:17
【问题描述】:

如何将关键字列表发送到宏并使用bind_quoted?这是一个示例:

带有宏的模块:

defmodule MacroTime do

  defmacro __using__(opts) do
    quote bind_quoted: [opts: opts] do

      def from_opts do
        # Using opts here produces an undefined function error
        IO.puts(opts[:foo])
      end

    end
  end

end

导入模块和脚本:

defmodule Main do
  use MacroTime, foo: "bar"
end

Main.from_opts

运行它会产生: ** (CompileError) main.ex:2: undefined function opts/0

您可以在这里试用:https://glot.io/snippets/eg2gg4huj3

我觉得我缺少一些关于宏的简单概念。

【问题讨论】:

  • 试试unquote(opts)[:foo]
  • @Dogbert 是的,没有引用绑定也可以工作,但我真的想在引用块的几个地方使用 opts[:foo] 并希望避免多次取消引用,因此 @ 987654327@

标签: metaprogramming elixir


【解决方案1】:

我认为这是因为您引用(绑定)的地方不正确。

有一个类似的问题是这样的: Elixir macros and bind_quoted

这是 Metaprogramming Elixir 一书中的定义:

绑定引用

quote 宏的 bind_quoted 选项将绑定传递给块, 确保外部绑定变量仅被引用一个 时间。

让我们更清楚。看看这个例子

defmodule Print do

  defmacro __using__(opts) do
    IO.puts "In macro's context #{__MODULE__}"    # Macro context
    quote bind_quoted: [opts: opts] do
      IO.puts "In caller's context #{__MODULE__}" # Caller context
      IO.inspect opts

      def opts do
        IO.puts "In function definition's context"
      end
    end
  end

end

编译:

iex(1)> defmodule Test do
...(1)> use Print, foo: "bar"
...(1)> end
In macro's context Elixir.Print
In caller's context Elixir.Test
[foo: "bar"]
{:module, Test,
 <<70, 79, 82, 49, 0, 0, 5, 24, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 127,
   131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115,
   95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...>>, {:opts, 0}}
iex(2)> Test.opts
In function definition's context
:ok
iex(3)>

要清楚,当你想注入代码你必须使用unquote

您在这里所做的是将绑定变量 opts 传递给引用块(调用者上下文),然后在内部调用它(函数定义的上下文)。

并澄清上下文的定义。这是来自书中的:

上下文是调用者的绑定、导入和别名的范围。 对于宏的调用者来说,上下文是宝贵的。它拥有你的观点 世界,并且由于不变性,你不期望你的 变量、导入和别名从你下面改变。

最后你打算使用bind_quoted。我建议你应该阅读Hygiene 保护调用者的上下文Overriding Hygiene 以考虑另一种适合你的目的的解决方案。

这是我到目前为止所想出来的。希望有所帮助!

【讨论】:

  • 我无法完全理解为什么它不起作用,如果我缺少一些东西来使它起作用。 ://
猜你喜欢
  • 2016-04-25
  • 2012-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-29
  • 1970-01-01
  • 2016-01-25
相关资源
最近更新 更多