Hi all
I would be very happy, if someone could explain me, what does quote return in a defmacro!
Reddit
Thanks
Hi all
I would be very happy, if someone could explain me, what does quote return in a defmacro!
Reddit
Thanks
quote
does transform the code in the “do
-block” into an Abstract Syntax Tree, which then can be injected into your program.
Thats it.
If this is not answering your original question, please be more specific and tell us your original question
Take a look on the code, this is the macro definition
defmodule ControlFlow do
defmacro unless(expression, do: block) do
quote do
if !unquote(expression), do: unquote(block)
end
end
end
So when I write in the iex shell
iex(16)> ControlFlow.unless 2 == 5, do: "block entered"
I am expecting an ast as the result but I’ve got block entered
value. So when I write
iex(3)> quote do: if 5 == 5, do: "Hello Foo"
{:if, [context: Elixir, import: Kernel],
[{:==, [context: Elixir, import: Kernel], [5, 5]}, [do:"Hello Foo"]]}
in the shell, I’ve got an ast not the value.
Thanks
quote
does return an ast. This happens at compile time.
So given your macro above, the following happens.
ControlFlow.unless 2 == 5, do: "block entered"
into iex.quote
returns, {:if, [context: Elixir, import: Kernel], [{:==, [context: Elixir, import: Kernel], [5, 5]}, [do:"Hello Foo"]]}
in this case."block entered"
.Elixir is a compiled language, and as such you always have to distinguish compile time and run time.
First of all, thanks explanation, now I have more question, can you say more about compile time and run time.
So when I compile a file, that contains macros with following statement
iex(1)> c "unless.exs"
and then require it:
iex(2)> require ControlFlow
and at the end call the macro.
ControlFlow.unless 2 == 5, do: "block entered"
How to code will compile and run?
I’ve found a macro definition in internet
defmacro example do {:+, [], [1, 2]} end
I return here an ast and when I call the macro, as the result I’ve got 3. That means, the shell will executed the returned ast?
As everything in Elixir, that is an expression, not a statement but an expression and returns the list of modules defined in the given file.
Since it is easier to explain, I will assume, that you have your module ControlFlow
as shown above and another one ControlFlowUsage
:
# control_flow_usage.ex
defmodule ControlFlowUsage do
require ControlFlow
def foo do
ControlFlow.unless 2 == 5, do: "block entered"
end
end
elixirc control_flow_usage.ex
ControlFlow.unless/2
and execute it.ControlFlowUsage.foo()
if !(2 == 5), do: "block entered"
"block entered"
in returnThis is a simplified process, in reality the process is more complex and optimisation processes might kick in.
This is pretty much the same as defmacro example, do: quote(do: 1 + 2)
, but less readable. In my opinion at least. Whatever gets returned by a macro is injected into the AST and if you return an invalid AST you will have a hard time to debug your error messages later on.
Thanks so much for your wonderful explaination.
I love elixir, that because annoying you with my question
Thanks …
I don’t consider questions beeing annoying. There are always three people learning from an answered question:
So feel free to ask further questions whenever you have them.