Elixir中map即便使用Macro.escape也无法正常unquote问题咨询
问题原因
你连续两次使用了Macro.escape转义map值,导致最终注入到代码中的是「map的AST结构的AST」,而非实际可运行的map值:
- 第一次转义:调用
use Foo时,你主动对%{:correct => true}做了Macro.escape处理,得到的是map对应的AST结构{:%{}, [], [correct: true]} - 第二次转义:在
__using__宏的Keyword.get逻辑中,你对传入的已经是AST的attrs值又做了一次Macro.escape,相当于把AST结构再次转义成了新的AST
最终unquote执行后,输出的就是第一次转义得到的AST结构,而非你预期的map值。
正确实现方式
最合理的方案是把转义逻辑统一封装在宏内部,使用方不需要感知转义操作,修改后代码如下:
defmodule Foo do defmacro __using__(options) do attrs = Keyword.get(options, :attrs, %{}) # 仅在宏内部统一做一次转义 escaped_attrs = Macro.escape(attrs) quote do def show, do: IO.inspect(unquote(escaped_attrs)) end end end defmodule MacroFix do use Foo, # 直接传原始map即可,不需要额外转义 attrs: %{correct: false} end
运行验证:
iex> MacroFix.show %{correct: false} %{correct: false}
如果需要保留使用方自行转义的逻辑,只需要删除__using__中Keyword.get的第二个参数里的Macro.escape即可,该方案会提高宏的使用门槛,不推荐。
内容的提问来源于stack exchange,提问作者Guilherme Torres Castro
相关产品推荐
相关产品推荐

