@@ -6,7 +6,7 @@ defmodule Protocol do
6
6
implementations. A protocol is defined with `Kernel.defprotocol/2`
7
7
and its implementations with `Kernel.defimpl/3`.
8
8
9
- ## A real case
9
+ ## Example
10
10
11
11
In Elixir, we have two nouns for checking how many items there
12
12
are in a data structure: `length` and `size`. `length` means the
@@ -102,8 +102,7 @@ defmodule Protocol do
102
102
invoking the protocol will raise unless it is configured to
103
103
fall back to `Any`. Conveniences for building implementations
104
104
on top of existing ones are also available, look at `defstruct/1`
105
- for more information about deriving
106
- protocols.
105
+ for more information about deriving protocols.
107
106
108
107
## Fallback to `Any`
109
108
@@ -165,6 +164,17 @@ defmodule Protocol do
165
164
The `@spec` above expresses that all types allowed to implement the
166
165
given protocol are valid argument types for the given function.
167
166
167
+ ## Configuration
168
+
169
+ The following module attributes are available to configure a protocol:
170
+
171
+ * `@fallback_to_any` - when true, enables protocol dispatch to
172
+ fallback to any
173
+
174
+ * `@undefined_impl_description` - a string with additional description
175
+ to be used on `Protocol.UndefinedError` when looking up the implementation
176
+ fails. This option is only applied if `@fallback_to_any` is not set to true
177
+
168
178
## Reflection
169
179
170
180
Any protocol module contains three extra functions:
@@ -828,7 +838,7 @@ defmodule Protocol do
828
838
quote bind_quoted: [ built_in: __built_in__ ( ) ] do
829
839
any_impl_for =
830
840
if @ fallback_to_any do
831
- quote do: unquote ( __MODULE__ . Any )
841
+ __MODULE__ . Any
832
842
else
833
843
nil
834
844
end
@@ -874,6 +884,9 @@ defmodule Protocol do
874
884
unquote ( any_impl_for )
875
885
end
876
886
887
+ undefined_impl_description =
888
+ Module . get_attribute ( __MODULE__ , :undefined_impl_description , "" )
889
+
877
890
@ doc false
878
891
@ spec impl_for! ( term ) :: atom
879
892
if any_impl_for do
@@ -882,17 +895,21 @@ defmodule Protocol do
882
895
end
883
896
else
884
897
Kernel . def impl_for! ( data ) do
885
- impl_for ( data ) || raise ( Protocol.UndefinedError , protocol: __MODULE__ , value: data )
898
+ impl_for ( data ) ||
899
+ raise ( Protocol.UndefinedError ,
900
+ protocol: __MODULE__ ,
901
+ value: data ,
902
+ description: unquote ( undefined_impl_description )
903
+ )
886
904
end
887
905
end
888
906
889
907
# Internal handler for Structs
890
908
Kernel . defp struct_impl_for ( struct ) do
891
- target =
892
- case Code . ensure_compiled ( Module . concat ( __MODULE__ , struct ) ) do
893
- { :module , module } -> module
894
- { :error , _ } -> unquote ( any_impl_for )
895
- end
909
+ case Code . ensure_compiled ( Module . concat ( __MODULE__ , struct ) ) do
910
+ { :module , module } -> module
911
+ { :error , _ } -> unquote ( any_impl_for )
912
+ end
896
913
end
897
914
898
915
# Inline struct implementation for performance
0 commit comments