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