简体   繁体   中英

Elixir - Extending the default 'receive' macro for a Process

I am currently experimenting with defining and using my own slightly adjusted receive macro, based on its default implementation. As a classic example, let's say I want to log every time a Process starts receiving a message from the mailbox. Could I define my own version of the receive macro that does the logging, then calls/uses the default receive macro and import this custom receive into my existing code?

Below is a not-working example to better illustrate what I am trying to achieve:

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} ->
        loop([value | state], ctr + 1)

      {from, :pop} ->
        [h | t] = state
        send(from, {:reply, h})
        loop(t, ctr)
    end

    loop(state, ctr)
  end
end

It's hard to override Kernel.SpecialForms macros because you can't import them like you could macros from anywhere else (you get a CompileError). I think your best bet is to name your macro something other than "receive".

Other problems you may be running into:

  1. You are defining your receive as a function instead of a macro. Elixir will try evaluating your do / after block as a literal keyword list, and that won't work well.
  2. receive/1 comes from Kernel.SpecialForms , not Kernel , so your import / :except won't work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM