Макроблок неожиданно возвращает [do: возвращаемое значение] - PullRequest
0 голосов
/ 10 июня 2018

У меня есть следующее определение внутри макроса:

defmacro route(pattern, options \\ [], block) do
  name = "my_fun"
  def unquote(name)(var!(conn)) do
    unquote(block)
  end
end

Я вызываю макрос с этой функцией:

route "/" do
  conn
  |> put_resp_content_type("text/plain")
  |> send_resp(200, "Hello, world!")

Внутренний блок возвращает структуру %Plug.Conn{},но когда я печатаю результаты unquote(block) в моем макросе, я получаю [do: %Plug.Conn{}] Что я делаю не так?Откуда появился список ключевых слов do? 1011 *

Большой фрагмент

defmacro route(pattern, options \\ [], block) do
  name = Keyword.get_lazy(options, :name, fn -> create_name(pattern, options) end)
  route = {pattern, name}
  quote do
    @routes [unquote(route) | @routes]
    def unquote(name)(var!(conn)) do
      resp = unquote(block)
      IO.puts("outside the block, resp is")
      IO.inspect(resp)
    end
  end
end

route "/" do
  resp = conn
  |> put_resp_content_type("text/plain")
  |> send_resp(200, "Hello, world!")
  IO.puts("Inside the block, resp is")
  IO.inspect(resp)
  resp
end

Результаты

Inside the block, resp is
%Plug.Conn{
  adapter: {Plug.Adapters.Cowboy2.Conn, :...},
  assigns: %{},
  {....SNIP....}
}

outside the block, resp is
[
  do: %Plug.Conn{
    adapter: {Plug.Adapters.Cowboy2.Conn, :...},
    assigns: %{},
    {....SNIP....}
  }
]

1 Ответ

0 голосов
/ 10 июня 2018

Вам нужно изменить аргумент с block на do: block:

defmacro route(pattern, options \\ [], do: block) do

A do ... end аргумент в вызове макроса Elixir передается как список ключевых слов из одного элемента с ключом :do.

Если вы не удалите это вложение с помощью шаблона, соответствующего ему как do: block, значение аргумента будет [do: block], а когда вы кавычки, вы удаляете кавычки [do: ...], чтотакже допустимое выражение и объясняет, почему ваш код работает и почему он печатает [do: ...].

...