【问题标题】:Unquote the result of a function defined by a macro取消引用由宏定义的函数的结果
【发布时间】:2018-10-19 22:39:08
【问题描述】:

我的宏有以下定义

defmacro defverified(sign, body) do 
  {name, _, [param]} = sign
  quote do
    def unquote(name)(unquote(param)) do  
      unquote(param) = verify! param
      unquote(body)
    end
  end
end

如果verify!/1 被验证为正确的参数,则返回其参数

而我的函数定义如下

defverified toto(p) do 
  IO.inspect p 
end 

并且检查p 的内容是正确的,但是函数的返回是我的变量的引用形式。

iex(3)> res = Toto.toto(1)
1
[do: 1]
iex(4)> res
[do: 1]

是否可以为我的函数的返回提供一个不带引号的表单,或者我应该手动取消引用它?
我希望我的函数有以下输出

iex(3)> res = Toto.toto(1)
1
1
iex(4)> res
1

【问题讨论】:

    标签: macros elixir


    【解决方案1】:

    这是因为do...end 构造是一种特殊的语法糖。例如,这个:

    def toto(p) do 
      IO.inspect p 
    end 
    

    相当于:

    def toto(p), do: IO.inspect p 
    

    其中,因为参数末尾的关键字作为关键字列表传递,所以相当于:

    def(toto(p), [do: IO.inspect(p)])
    

    由于您的 defverified 宏只需要 do 块并且没有其他关键字参数,因此我们可以显式匹配实际的主体:

    defmacro defverified(sign, [do: body]) do 
    ...
    

    在此之前,toto 函数中的最后一个形式实际上是:

    [do: IO.inspect param]
    

    这将按预期调用IO.inspect,但随后返回关键字列表而不是普通值。

    【讨论】:

    • 你领先我一分钟 :) 顺便说一句,(sign, [do: body]) 中不需要方括号。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-07
    • 2010-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多