Packages

Automatically creates a behaviour from a module's specs.

Current section

Files

Jump to
behaves_like lib behaves_like.ex
Raw

lib/behaves_like.ex

defmodule BehavesLike do
@moduledoc """
Turns a module's specs into callbacks.
Lets you state that a module behaves like another, without writing behaviour callbacks.
For example:
```elixir
defmodule API do
use BehavesLike
@spec get(binary()) :: {:ok, any()} | {:error, any()}
def get(id) do
Backend.get(id)
end
end
defmodule Backend do
@behaviour API
@impl true
def get(id) do
database().get(id)
end
end
```
"""
defmacro __using__(_opts) do
quote do
@before_compile unquote(__MODULE__)
end
end
defmacro __before_compile__(_env) do
quote do
{_set, bag} = :elixir_module.data_tables(__MODULE__)
unquote(__MODULE__).get_typespecs(bag, :spec)
|> Enum.each(&unquote(__MODULE__).store_typespec(bag, :callback, &1))
end
end
@doc false
def get_typespecs(bag, type) do
:ets.lookup_element(bag, type, 2)
end
@doc false
def store_typespec(bag, key, value) do
:ets.insert(bag, {key, value})
:ok
end
end