Guillaume Milan
Guillaume Milan

Reputation: 39

Unquote the result of a function defined by a macro

I have the following definition of my macro

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

Were verify!/1 returns its paramters if it is verified as a correct parameter

And my function is defined as follows

defverified toto(p) do 
  IO.inspect p 
end 

And the inspection of the content of p is correct but the return of the function is a quoted form of my variable.

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

Is it possible to have an unquoted form for the return of my function or should I unquote it manually?
I expect the following output of my function

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

Upvotes: 0

Views: 163

Answers (1)

legoscia
legoscia

Reputation: 41548

This happens because the do...end construct is a peculiar piece of syntactic sugar. For example, this:

def toto(p) do 
  IO.inspect p 
end 

is equivalent to:

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

which, because keywords at the end of an argument get passed as a keyword list, is equivalent to:

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

Since your defverified macro only expects a do block and no other keyword parameters, we can explicitly match out the actual body:

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

Before doing this, the last form in the toto function would literally be:

[do: IO.inspect param]

which would call IO.inspect as expected but then return a keyword list instead of a plain value.

Upvotes: 2

Related Questions