vinhnglx / vinhnglx.github.io

0 stars 0 forks source link

TIL_15_June_2017 - Polymorphism with Protocols in Elixir #7

Open vinhnglx opened 7 years ago

vinhnglx commented 7 years ago

Polymorphism is the ability in programming to present the same interface for differing underlying forms -- (source: djm's blog)

From the Elixir in Action book, polymorphism is a runtime decision about which code to execute, based on the nature of the input data. In Elixir, the basic way of doing this is by using the language feature called Protocols.

iex > [1,2,3,4,5] |> Enum.map(fn(x) -> x* 2 end)
[2,4,6,8,10]

iex > %{first_name: "Vincent", last_name: "Nguyen"} |> Enum.map(fn({k, v}) -> IO.puts v end)
Vincent
Nguyen

From the example above, we can see the input data of Enum.map/2 can be a list, a map, range etc. So, how does the Enum.map/2 know how to walk each structure?. It doesn't.

The code in Enum.map/2 is generic and relies on a contract. This contract called a Protocol must be implemented for each data type you wish to use with Enum functions.

So, the protocol's concept is quite similar to abstract interfaces from OOP languages.

vinhnglx commented 7 years ago

A protocol is a module in which you declare functions without implementing them.

In the example above, Enum is a protocol - here is the source

If the protocol isn't implemented for the given data types, an error will raised

iex > [1,2,3,4,5] |> Enum.map(fn(x) -> x* 2 end)
[2,4,6,8,10]

iex> Vincent |> Enum.map(fn(x) -> x* 2 end)
** (Protocol.UndefinedError) protocol Enumerable not implemented for Vincent
vinhnglx commented 7 years ago

How to implement a protocol for a specific type

We start the implementation by calling the defimpl macro, then you specify which protocol to implement and the corresponding data type.

vinhnglx commented 7 years ago

Built-in protocols in Elixir

Detail can read from Elixir documentation.