即使使用 Macro.escape,取消引用也不适用于地图
Unquoute not working for maps even with Macro.escape
我有以下代码:
defmodule Foo do
defmacro __using__(options) do
attrs = Keyword.get(options, :attrs, Macro.escape(%{}))
quote do
def show, do: IO.inspect(unquote(attrs))
end
end
end
defmodule MacroBug do
use Foo,
attrs: Macro.escape(%{:correct => true})
end
此代码打印:
iex(5)> MacroBug.show
{:%{}, [], [correct: true]}
{:%{}, [], [correct: true]}
应该是%{correct: false}
,不是吗?如果不是,正确的方法是什么
如 the documentation 所示,应该明确 Macro.escape/2
values.
在您的示例中,问题是您实际上两次引用了地图。检查这三个宏:
defmodule Escape do
defmacro q(opts) do
IO.inspect(opts, label: "quote")
quote do: IO.inspect(unquote(opts), label: "unquote")
end
defmacro e(opts) do
value = IO.inspect(Macro.escape(%{foo: %{}}), label: "escape")
quote do: IO.inspect(unquote(value), label: "unescape")
end
defmacro e!(opts) do
value = IO.inspect(%{foo: %{}}, label: "escape!")
quote do: IO.inspect(unquote(value), label: "unescape!")
end
end
前两个相当等价,并且很高兴地产生了预期的结果。
iex|1 ▸ Escape.q %{foo: %{}}
escape: {:%{}, [], [foo: {:%{}, [], []}]}
unescape: %{foo: %{}}
%{foo: %{}}
iex|2 ▸ Escape.q %{foo: %{}}
quote: {:%{}, [], [foo: {:%{}, [], []}]}
unquote: %{foo: %{}}
%{foo: %{}}
第三个,虽然,加注,因为不能通过 AST 转换边界 %{foo: %{}}
。也就是说,对于后一种情况,就像在宏上下文中创建的值一样,应该对其进行转义。
对于从宏外部传递的值,elixir 为您完成。
我有以下代码:
defmodule Foo do
defmacro __using__(options) do
attrs = Keyword.get(options, :attrs, Macro.escape(%{}))
quote do
def show, do: IO.inspect(unquote(attrs))
end
end
end
defmodule MacroBug do
use Foo,
attrs: Macro.escape(%{:correct => true})
end
此代码打印:
iex(5)> MacroBug.show
{:%{}, [], [correct: true]}
{:%{}, [], [correct: true]}
应该是%{correct: false}
,不是吗?如果不是,正确的方法是什么
如 the documentation 所示,应该明确 Macro.escape/2
values.
在您的示例中,问题是您实际上两次引用了地图。检查这三个宏:
defmodule Escape do
defmacro q(opts) do
IO.inspect(opts, label: "quote")
quote do: IO.inspect(unquote(opts), label: "unquote")
end
defmacro e(opts) do
value = IO.inspect(Macro.escape(%{foo: %{}}), label: "escape")
quote do: IO.inspect(unquote(value), label: "unescape")
end
defmacro e!(opts) do
value = IO.inspect(%{foo: %{}}, label: "escape!")
quote do: IO.inspect(unquote(value), label: "unescape!")
end
end
前两个相当等价,并且很高兴地产生了预期的结果。
iex|1 ▸ Escape.q %{foo: %{}}
escape: {:%{}, [], [foo: {:%{}, [], []}]}
unescape: %{foo: %{}}
%{foo: %{}}
iex|2 ▸ Escape.q %{foo: %{}}
quote: {:%{}, [], [foo: {:%{}, [], []}]}
unquote: %{foo: %{}}
%{foo: %{}}
第三个,虽然,加注,因为不能通过 AST 转换边界 %{foo: %{}}
。也就是说,对于后一种情况,就像在宏上下文中创建的值一样,应该对其进行转义。
对于从宏外部传递的值,elixir 为您完成。