Powered by AppSignal & Oban Pro

Quote and unquote

meta-programming-in-elixir.livemd

Quote and unquote

Quoting

quote sempre retorna uma tupla de 3 posição:

  1. nome da função
  2. metadados
  3. argumentos da função
quote do: sum(1, 2, 3)
quote do: 1 + 2
quote do: %{1 => 2}
# mas no caso de variável, a última posição não é o argumento
quote do: x
quote do: sum(1, 2 + 3, 4)
Macro.to_string(quote do: sum(1, 2 + 3, 4))

Normalmente o quote retorna o seguinte formato:

{atom | tuple, list, list | atom}

1º) é um atom ou outra tupla nesse formato

2º) é uma keywork list com metadados como números e contextos

3º) é uma lista de argumentos quando o primeiro for uma função, ou um atom quando o primeiro for uma variável

Existem literais que o quote retorna o próprio elemento:

IO.puts("Atoms")
quote do: :sum
IO.puts("Numbers")
quote do: 1.0
IO.puts("Lists")
quote do: [1, 2]
IO.puts("Strings")
quote do: "strings"
IO.puts("Tuples with two elements")
quote do: {1, 2}
quote do: String.upcase("foo")
quote do: if(true, do: :this, else: :that)
quote do: if(true) do
  :this
else
  :that
end
quote do:
        (if true do
           :this
         else
           :that
         end)

Unquoting

number = 13
Macro.to_string(quote do: 11 + number)
number = 13
Macro.to_string(quote do: 11 + unquote(number))
fun = :hello
Macro.to_string(quote do: unquote(fun)(:world))
inner = [3, 4, 5]
Macro.to_string(quote do: [1, 2, unquote_splicing(inner), 6])
quote do: %{1 => 2}
map = %{hello: :world}
Macro.escape(map)
map = %{hello: :world}
quote do: map

OBS: alguns elementos não podem ser explicitamente convertidos para quote:

pid = spawn(fn -> 1 end)
Macro.escape(pid)

###

defmodule X do
  def f do
    10
  end
end

Macro.escape(X.f())