Proposal: `defcast` and `defcall` syntax sugar for GenServers

41 views
Skip to first unread message

Brandon Gillespie

unread,
Nov 20, 2022, 8:32:21 AM11/20/22
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
```

José Valim

unread,
Nov 20, 2022, 8:57:54 AM11/20/22
to elixir-l...@googlegroups.com
Hi Brendon,

Note that this has been explored in libraries before, such as ExActor, and then abandoned.

I have the same concerns as Saša in the linked comment.

Others are welcome to further explore those ideas in libraries. Saša has suggestions of alternative approaches to consider in the same link.

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/8337ca38-4718-700a-0708-81968d2875bf%40cold.org.
Reply all
Reply to author
Forward
0 new messages