Skip to content

Commit 34f0254

Browse files
acconradjosevalim
authored andcommitted
Improve documentation for Protocol.derive (#7073)
1 parent 91ededc commit 34f0254

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

lib/elixir/lib/kernel.ex

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4002,8 +4002,9 @@ defmodule Kernel do
40024002
For each protocol in the `@derive` list, Elixir will assert there is an
40034003
implementation of that protocol for any (regardless if fallback to any
40044004
is `true`) and check if the any implementation defines a `__deriving__/3`
4005-
callback. If so, the callback is invoked, otherwise an implementation
4006-
that simply points to the any implementation is automatically derived.
4005+
callback (via `Protocol.derive/3`). If so, the callback is invoked,
4006+
otherwise an implementation that simply points to the any implementation
4007+
is automatically derived.
40074008
40084009
## Enforcing keys
40094010

lib/elixir/lib/protocol.ex

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,55 @@ defmodule Protocol do
116116

117117
@doc """
118118
Derives the `protocol` for `module` with the given options.
119+
120+
If your implementation passes options or if you are generating
121+
custom code based on the struct, you will also need to implement
122+
a macro defined as `__deriving__(module, struct, options)`
123+
to get the options that were passed.
124+
125+
## Examples
126+
127+
defprotocol Derivable do
128+
def ok(a)
129+
end
130+
131+
defimpl Derivable, for: Any do
132+
defmacro __deriving__(module, struct, options) do
133+
quote do
134+
defimpl Derivable, for: unquote(module) do
135+
def ok(arg) do
136+
{:ok, arg, unquote(Macro.escape(struct)), unquote(options)}
137+
end
138+
end
139+
end
140+
end
141+
142+
def ok(arg) do
143+
{:ok, arg}
144+
end
145+
end
146+
147+
defmodule ImplStruct do
148+
@derive [Derivable]
149+
defstruct a: 0, b: 0
150+
151+
defimpl Sample do
152+
def ok(struct) do
153+
Unknown.undefined(struct)
154+
end
155+
end
156+
end
157+
158+
Explicit derivations can now be called via `__deriving__`:
159+
160+
# Explicitly derived via `__deriving__`
161+
Derivable.ok(%ImplStruct{a: 1, b: 1})
162+
163+
# Explicitly derived by API via `__deriving__`
164+
require Protocol
165+
Protocol.derive(Derivable, ImplStruct, :oops)
166+
Derivable.ok(%ImplStruct{a: 1, b: 1})
167+
119168
"""
120169
defmacro derive(protocol, module, options \\ []) do
121170
quote do

0 commit comments

Comments
 (0)