Erlang 2: Modules

eric | July 1, 2019, 6:59 p.m.

Comments to the book "Learn You Some Erlang For Great Good" by Fred Hébert, Chapter 2 - Modules. Understanding how modules work and how they should be organized. Learning goals: How to create a module. How to export functions in modules.

Learn You Some Erlang For Great Good by Fred HébertThis article series has come about as a result of my efforts to learn Erlang. In order to learn the language, I am reading the book "Learn You Some Erlang For Great Good" by Fred Hébert. Every time I come across something that I find difficult to understand I will make an effort to understand it and explain my understanding in detail. I will also - as far as possible - site alternative sources, possible exercises and more. First off, maybe you could be a pal and buy Fred Herbert's book. There is a huge effort behind that book and I think Fred deserve our support. You can get it at No Starch Press.

I must admit that I am cheating a bit, because I read ahead quite a few chapters before rereading an earlier chapter and then commenting on that chapter on this site. This is to discover what is important to remember and / or easy to forget as I dig deeper into the content.

Each article has a list of references that I stongly suggest you have a look at, including the Erlang Language Reference, the ETS reference and Joe Armostrong's book Programming Erlang.

Creating Modules

Logically, you should put functions about similar things inside a single module. Common operations on lists are kept in the lists module, while functions to do input and output (such as writing to the terminal or in a file) are regrouped in the io module.

This is a big break from OOP. You gather functions in modules based on what operations they handle, instead of focusing on objects and their methods. Note that functions with the same name but different arity are completely different functions.

Exporting Functions from Modules

Functions that are not exported from a module can be called only from within a module. Exported functions are equivalent to public methods in an object-oriented programming language (OOPL); nonexported functions are equivalent to private methods in an OOPL.

Remember to define the functions to be exported. The export_all should just be used for testing.

-module(erlangmodules).
-compile(export_all).

first_print_fun(Whattoprint) ->
    io:format("Hactar is printing: ~p~n",[Whattoprint]).

second_print_fun(Whattoprint) ->
    internal_print_fun(Whattoprint).

internal_print_fun(Whattoprint) ->
    io:format("Hactar is printing: ~p~n",[Whattoprint]),
    io:format("Krikkiters rule!").

Compiling this and running it in the shell:

Example of export_all in the Erlang shell

With export_all, you have access to the internal function from outside of the module. This goes against encapsulation (in the OOP sense of the term) and may complicate maintenance. export_all is often used while programming and testing the code. However, it is easy to forget to replace the export_all with the names of the modules that are supposed to be exported.  It is better to define the functions to be available outside of the module in compile and then use compiler flags to export all functions for testing:

-module(erlangmodules2).
-export([first_print_fun/1, second_print_fun/1]).

first_print_fun(Whattoprint) ->
    io:format("Hactar is printing: ~p~n",[Whattoprint]).

second_print_fun(Whattoprint) ->
    internal_print_fun(Whattoprint).

internal_print_fun(Whattoprint) ->
    io:format("Hactar is printing: ~p~n",[Whattoprint]),
    io:format("Krikkiters rule!~n").

Compiling without compiler flags gives us:

Erlang compile-instruction in scripts

If we include the export_all flag in the compile-instruction, we may access the internal function (you still need to remember to include the module name when calling the function, though):

Erlang module compilation with the export_all flag set

Compiling With HiPE

Compiling for native platforms to achieve higher performance is briefly mentioned. What is not mentioned is that you need to install the

erlang-base-hipe

package to be able to use HiPE. That is not mentioned, something that got me a bit confused.

References

  • http://learnyousomeerlang.com/modules
  • Programming Erlang, 4 - Modules and Functions
  • Erlang Reference Manual, Modules - http://erlang.org/doc/reference_manual/modules.html
  • Why is -compile(export_all) bad practice? https://stackoverflow.com/questions/7863087/why-is-compileexport-all-bad-practice
  • Missing HiPE in Erlang R18? - https://stackoverflow.com/questions/37305970/hipe-not-found-in-erlang-r18/37306313#37306313
  • Erlang Compiler Reference Manual - http://erlang.org/doc/man/compile.html

Other Erlang Resources

Sites

The Erlang main site

Erlang Reference Manual User's Guide

Erldocs - An alternative to the official sites.

Erlang Patterns - A collection of Erlang patterns

Rebar3 - A build tool for Erlang that makes it easy to compile and test Erlang applications and releases.

Communities

Erlang mailing lists and forums

The Google group Erlang Programming

Erlang on Stack Exchange

Erlang on Freenode - Use #Erlang

Erlang on Slack

Books

"Learn You Some Erlang For Great Good", by Fred Hebert

"Programming Erlang", by Joe Armstrong

Articles

The Zen of Erlang, by Fred Hebert. A partly practical, partly philosophical take on Erlang.

Other

Ericsson's coding standard for Erlang - Programming rules and conventions.

Getting started with Erlang using IntelliJ IDEA (including Rebar3).

About Me

Experienced dev and PM. Data science, DataOps, Python and R. DevOps, Linux, clean code and agile. 10+ years working remotely. Polyglot. Startup experience.
LinkedIn Profile

By Me

Statistics & R - a blog about - you guessed it - statistics and the R programming language.
R-blog

Erlang Explained - a blog on the marvelllous programming language Erlang.
Erlang Explained