取消引用由宏定义的函数的结果

时间:2018-10-19 14:09:40

标签: macros elixir

我对宏有以下定义

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

1 个答案:

答案 0 :(得分:2)

之所以会这样,是因为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,但随后返回关键字列表而不是简单值。