Sharing Base Functionality in Elixir

Steven Blowers
Nov 19, 2018 · 3 min read

At Rekki we write a lot of Elixir code. Elixir is a language whose influences are a mix between object-oriented programming and functional programming. This is evident in how it provides tools typically of an object-oriented style in a functional way.

One such implementation of these tools is for polymorphism, which is the idea that something (function / module) can have different forms, based on the type of input. These tools are Behaviours and Protocols.

You would use Protocol when the desired behaviour of the functions are the same, but the data type is different. Here is an example: a Protocol for a size function, the desire of all the functions is the calculate the length of the input, but the data type is different, here is the example from the Elixir website:

Protocol

Behaviours are used when the desire of the modules are the same, but the situation is different. An example being parser modules, the desire of each module is to parse data of a specific format, the situation of what that format is changes, here is another example from the Elixir website:

Behaviour

Now that we’ve seen how you can achieve polymorphism in Elixir, how would we allow each implementation to share functionality?

By making use of a mix of either Behaviour or Protocol along with the use macro, then polymorphism and extension can be achieved at the same time.

An example would be a FilePrinter Protocol, it would parse a file in a particular format and then print that to standard output. The parsing of the file would change based on the file type, but the way it would print would remain the same. Therefore, we would only want to write the implementation of how its prints to standard output once, and this would be shared between all implementations:

use Macro

And an example of the Behaviour being implemented:

Implementation

We would then be able to call JSONPrinter in the following manner:

Usage

It might seem strange at first, using both use and @behaviour on the module. It also looks like we are introducing coupling where it is not needed, coupling the implementation of the parser to the implementation of how it is output. What if we wanted to extend the functionality of the parser, maybe to parse JSON as it comes in from a web request? This is true, coupling has been introduced where it doesn’t need to be, however this coupling has allowed the possiblity of some benefits: duplicated code is kept to a minimum, being able to add new scenarios does not require much code and the user of this code is presented with a clean interface to work with.

In the blog post you have seen how to share functionality between different implementations of a Protocol or Behaviour with the use of the use macro. It may not fit every situation, so take a critical eye to it before deciding to implement it yourself, but under the right circumstances it is a great asset to have when implementing polymorphism in Elixir.

Want to know more about us? Go here.

REKKI team

REKKI is a free mobile app that lets you order and chat…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store