Brandon Gillespie
unread,Nov 20, 2022, 8:32:21 AM11/20/22Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Sign in to report message
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to elixir-l...@googlegroups.com
Anybody working with GenServers realizes there is a LOT of tedious
boilerplating, and it leaves the code a bit of a spaghetti incident that
is difficult to read. Could there be a way to reduce this and make the
code more readable, at least for the most common cases?
There are many ways this might work, so this is just one proposal.
Add`defcast` and `defcall` for GenServer, as sugar to help with some of
the boilerplating (for each cast and call). In this proposal, one
`defcast` or `defcall` defines two functions, the wrapper and the
defined function (the wrapper is the "internal" or hidden function, and
the "defined" function is the one with the programmer's code). In this
context:
- A semicolon is used to separate internal vs defined arguments—any
more appropriate token can be used, this is just used to demonstrate the
example
- adds a `target: ` function header key, which defaults to __MODULE__
# CAST Example 1:
```elixir
defcast do_a_thing(arg1; state) do
...code
{:noreply, %{state | ...}}
end
```
Is equivalent to:
```elixir
def do_a_thing(arg1), do: GenServer.cast(__MODULE__, {:do_a_thing, arg1})
def handle_cast({:do_a_thing, arg1}, state) do
...code
{:noreply, %{state | ...}}
end
```
# CAST Example 2:
```elixir
defcast do_a_thing(arg1, pid; state), target: pid do
...code
{:noreply, %{state | ...}}
end
```
Is equivalent to:
```elixir
def do_a_thing(arg1, pid), do: GenServer.cast(pid, {:do_a_thing, arg1})
def handle_cast({:do_a_thing, arg1}, state) do
...code
{:noreply, %{state | ...}}
end
```
# CALL Example 1
```elixir
defcall do_a_thing(arg1; from, state) do
...code
{:noreply, %{state | ...}}
end
```
Is equivalent to:
```elixir
def do_a_thing(arg1), do: GenServer.call(__MODULE__, {:do_a_thing, arg1})
def handle_cast({:do_a_thing, arg1}, from, state) do
...code
{:noreply, %{state | ...}}
end
```