Эликсир — Расширение макроса «получение» по умолчанию для процесса

#macros #elixir #actor #extends

Вопрос:

В настоящее время я экспериментирую с определением и использованием моего собственного слегка скорректированного receive макроса, основанного на его реализации по умолчанию. В качестве классического примера предположим, что я хочу регистрироваться каждый раз, когда процесс начинает получать сообщение из почтового ящика. Могу ли я определить свою собственную версию receive макроса, который ведет журнал, затем вызывает/использует receive макрос по умолчанию и импортирует этот пользовательский прием в мой существующий код?

Ниже приведен неработающий пример, чтобы лучше проиллюстрировать, чего я пытаюсь достичь:

 defmodule MyWeirdReceive do  def receive(args) do  IO.puts "I just started receiving a message from the mailbox"  Kernel.SpecialForms.receive(args)  end end   defmodule Stack do  import Kernel, except: [receive: 1]  import MyWeirdReceive  def loop(state, ctr) do  receive do  {_from, :push, value} -gt;  loop([value | state], ctr   1)   {from, :pop} -gt;  [h | t] = state  send(from, {:reply, h})  loop(t, ctr)  end   loop(state, ctr)  end end  

Ответ №1:

Трудно переопределить Kernel.SpecialForms макросы, потому что вы не можете импортировать их, как макросы, из любого другого места (вы получаете ошибку компиляции). Я думаю, что вам лучше всего назвать свой макрос чем-то иным, чем «получать».

Другие проблемы, с которыми вы можете столкнуться:

  1. Вы определяете получение как функцию, а не как макрос. Elixir попытается оценить ваш do / after блок как буквальный список ключевых слов, и это не сработает хорошо.
  2. receive/1 происходит от Kernel.SpecialForms , нет Kernel , поэтому ваш import / :except не будет работать.