48
votes

Behaviours define callbacks & protocols define methods without signatures. Modules implementing a protocol should give definition for all those methods. Same for modules using a behaviour. What is the semantic difference?

One difference I can think of is, a protocol can be implemented for a single type only once where as we can implement a behaviour for a module multiple times based on our requirements. I am clear with when to use what. Is there any other difference other than this?

2
Also, most importantly, behaviours start new processes where the callbacks are run while the protocol functions are run in the same process. This is the same comment as below, but it is often missed. Behaviours hide all the concurrency and message passing but they are still there and the client calls and callback calls are run in different processes. - rvirding
@rvirding I didn't know it and I don't remember seeing that in any book or tutorial. Is there any part of documentation or any other article about how behaviors start new processes implicitly? - Krzysztof Wende
@KrzysztofWende It is implicitly stated in erlang.org/doc/design_principles/des_princ.html . Basically the term behaviour is deeply connected to OTP applications and therefore to supervision trees which are all about maintaining processes. In Erlang, a behaviour abstracts away common patterns (client-server, state machine etc) so that you don't have to call spawn* and pattern match messages manually (which is error prone). Fred Hebert's online tutorial helped me a lot to understand this: learnyousomeerlang.com/… - toraritte

2 Answers

52
votes

Protocol is type/data based polymorphism. When I call Enum.each(foo, ...), the concrete enumeration is determined from the type of foo.

Behaviour is a typeless plug-in mechanism. When I call GenServer.start(MyModule), I explicitly pass MyModule as a plug-in, and the generic code from GenServer will call into this module when needed.

31
votes

Answered by José Valim on the same topic ( from google thread, https://groups.google.com/forum/#!msg/elixir-lang-talk/S0NlOoc4ThM/J2aD2hKrtuoJ )

A protocol is indeed a behaviour + dispatching logic.

However I think you are missing the point of behaviours. Behaviours are extremely useful. For example, a GenServer defines a behaviour. A behaviour is a way to say: give me a module as argument and I will invoke the following callbacks on it, which these argument and so on. A more complex example for behaviours besides a GenServer are the Ecto adapters.

However, this does not work if you have a data structure and you want to dispatch based on the data structure. Hence protocols.