Hi,
I’ve been learning elixir macros for some time and I’m doing so by trying to implement a small library similar in scope to https://github.com/sasa1977/exactor. Basically a set of macros to simplify common GenServer boilerplate.
Here is a simple example how it looks like.
defmodule CounterAgent do
use Stone.GenServer
defstart start_link(val \\ 0) do
initial_state(val)
end
defcall get(), state: state do
reply(state)
end
end
And then the usage is:
{:ok, pid} = CounterAgent.start_link(5)
CounterAgent.get(pid)
What I wanted to implement as a next step was an option to generate “singleton” GenServers, like that:
defmodule CounterAgent do
use Stone.GenServer, singleton: CounterAgent
defstart start_link(val \\ 0) do
initial_state(val)
end
defcall get(), state: state do
reply(state)
end
end
So that the server would automatically register under the name CounterAgent
so that no pid
would need to be supplied to the calls:
CounterAgent.start_link(5)
CounterAgent.get()
The problem I have is about how to propagate the singleton
parameter from the __using__
macro to a defcall
macro. I can easily set the module attribute @singleton
to that value, but then since macros only operate on code, there is no easy way to access the value of module attribute @singleton
in a macro. I know that an approach like that works:
defmacro defcall(...) do
quote do
if @singleton do
unquote(def_call_fun(singleton: true))
else
unquote(def_call_fun(singleton: false))
end
end
end
What is a good way to solve this issue?