How to generate fallback functions with metaprogramming?

I want to add fallback functions to many modules.

ex)

Instead of

defmodule FirstGenServer do
  def handle_info(:event, state) do
    # do something
    {:noreply, state}
  end
  def handle_info(_, state) do
    {:noreply, state}
  end
end

defmodule SecondGenServer do
  def handle_info(:event, state) do
    # do something
    {:noreply, state}
  end
  def handle_info(_, state) do
    {:noreply, state}
  end
end

Do like this

defmodule MyMacro do
  defmacro __using__(_opts) do
    # ??
  end
end

defmodule FirstGenServer do
  use MyMacro

  def handle_info(:event, state) do
    # do something
    {:noreply, state}
  end
end

defmodule SecondGenServer do
  use MyMacro

  def handle_info(:event, state) do
    # do something
    {:noreply, state}
  end
end

Can I do that?

Is it possible to append code below modules with metaprogramming?

Yes, you could use @before_compile MyFallbacks instead of use MyMacro the difference is with the former the code returned by MyFallback.before_compile(env) will be added to the module after the user defined all its functions but before it gets compiled. So you can test if the user did define some function (with Module.defines?/2) and if not, you can provide a default implementation.

Search on the Module docs for @before_compile attribute.

1 Like

It works perfect! Thanks

Ignoring stray messages coming into your genserver might not be the best approach. There shouldn’t really be such messages and any unhandled message, in my opinion, requires an exception thrown or at least an error logged.

4 Likes

I agree with you, but I will use this on Phoenix channels and clients can’t know what happens if channels crash.