#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
макросы, потому что вы не можете импортировать их, как макросы, из любого другого места (вы получаете ошибку компиляции). Я думаю, что вам лучше всего назвать свой макрос чем-то иным, чем «получать».
Другие проблемы, с которыми вы можете столкнуться:
- Вы определяете получение как функцию, а не как макрос. Elixir попытается оценить ваш
do
/after
блок как буквальный список ключевых слов, и это не сработает хорошо. receive/1
происходит отKernel.SpecialForms
, нетKernel
, поэтому вашimport
/:except
не будет работать.