Implementing Any
Manually implementing protocols for all structs can quickly become repetitive and tedious. In such cases, Elixir provides two options: we can explicitly derive the protocol implementation for our types or automatically implement the protocol for all types. In both cases, we need to implement the protocol for Any
.
Deriving
Elixir allows us to derive a protocol implementation based on the Any
implementation. Let’s first implement Any
as follows:
defimpl Blank, for: Any do
def blank?(_), do: false
end
Now, when defining the struct, we can explicitly derive the implementation for the Blank
protocol. Let’s create another struct, this one called DeriveUser
:
defmodule DeriveUser do
@derive Blank
defstruct name: "john", age: 27
end
When deriving, Elixir will implement the Blank
protocol for DeriveUser
based on the implementation provided for Any
. Note this behaviour is opt-in: structs will only work with the protocol as long as they explicitly implement or derive it.
Fallback to Any
Another alternative to @derive
is to explicitly tell the protocol the fallback to Any
when an implementation cannot be found. This can be achieved by setting @fallback_to_any
to true
in the protocol definition:
defprotocol Blank do
@fallback_to_any true
def blank?(data)
end
Assuming we have implemented Any
as in the previous section:
defimpl Blank, for: Any do
def blank?(_), do: false
end
Now all data types (including structs) that we have not implemented the Blank
protocol will be considered non-blank. In contrast to @derive
, falling back to Any
is opt-out: all data types get a pre-defined behaviour unless they provide their own implementation of the protocol. Which technique is best depends on the use case but, given Elixir developers prefer explicit over implicit, you may see many libraries pushing towards the @derive
approach.