Search code examples
macrosescapingelixirquote

Elixir quote vs escape


When, in Elixir, should one use Macro.escape/1 instead of quote/1? I've looked at the beginner's guide and it's not helping.


Solution

  • quote/2 returns the abstract syntax tree (AST) of the passed in code block.

    Macro.escape/2 returns the AST of the passed in value.

    Here is a example:

    iex(1)> a = %{"apple": 12, "banana": 90}
    %{apple: 12, banana: 90}
    
    iex(2)> b = quote do: a
    {:a, [], Elixir}
    
    iex(3)> c = Macro.escape(a)
    {:%{}, [], [apple: 12, banana: 90]}
    

    quote/2 will keep the origin variable a, while Macro.escape/2 will inject a's value into the returned AST.

    iex(4)> Macro.to_string(b) |> Code.eval_string
    
      warning: variable "a"  does  not exist and is being
      expanded to "a()", please use parentheses to remove
      the ambiguity or change the variable name
        nofile:1
    
    iex(5)> Macro.to_string(c) |> Code.eval_string
    {%{apple: 12, banana: 90}, []}
    
    iex(6)> Macro.to_string(b) |> Code.eval_string([a: "testvalue"])
    {"testvalue", [a: "testvalue"]}
    

    For completeness' sake:

    iex(1)> a = %{"apple": 12, "banana": 90}
    %{apple: 12, banana: 90}
    
    iex(3)> Macro.escape(a)
    {:%{}, [], [apple: 12, banana: 90]}
    
    iex(2)> quote do: %{"apple": 12, "banana": 90}
    {:%{}, [], [apple: 12, banana: 90]}