将关键字列表发送到宏并使用 bind_quoted

Sending a keyword list to a macro and using bind_quoted

如何将关键字列表发送到宏并使用 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

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

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

有一个类似的问题是这样的:

这是 Metaprogramming Elixir 一书中的定义:

bind_quoted

The quote macro’s bind_quoted option passes a binding to the block, ensuring that the outside bound variables are unquoted only a single time.

让我们clearer.Take看看这个例子

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传递给引用块(调用者上下文)然后你在里面调用它(函数定义的上下文).

并澄清 context.This 的定义来自本书:

A context is the scope of the caller’s bindings, imports, and aliases. To the caller of a macro, the context is precious. It holds your view of the world, and by virtue of immutability, you don’t expect your variables, imports, and aliases to change out from underneath you.

您打算使用的最后一个 bind_quoted。我建议您阅读 卫生保护调用者的上下文压倒卫生考虑另一种解决方案来满足您的目的。

这是我想出来的,所以 far.Hope 很有帮助!