## Erlang

Erlang was the first functional programming language I took a shot at learning. I started with the Manning book Erlang in Action which also explained the OTP. The problem was that I was combining learning functional programming with the pretty fringe environment that is Erlang. So instead I took a break from that and decided to learn Haskell, and loved it.

Now I'm back and would like to pick up Erlang and its OTP library. Even if I don't end up using it, I think it'll teach me many interesting concepts that lend themselves to this new age of massively concurrent programs. Scala, for example, uses actor-based concurrency much like Erlang's, as well as supervision trees.

# Modules

Modules generally take the following form. The first line contains the module directive, known as the export declaration, as in Haskell. This lists the functions and their arity.

-module(hello).
export([start/0]).

start() ->
io:format("Hello world~n").


This can be compiled from the shell with the c(modulename) command. However, it's more likely to be compiled with the Erlang compiler erlc, which produces a beam file. It's possible to then run the program can then be run on the Erlang virtual machine with the erl command, which uses -s to specify the functions to evaluate, in order.

$erlc hello.erl$ erl -noshell -s hello start -s init stop


The following describes a file server. It defines a convenience function start which spawns a process that forever performs the loop function inside a particular directory, which simply waits for a message to be received and processes it. Notice that loop performs a tail-recursive call; Erlang has tail-call optimization, so there's no need to worry about overflowing the stack.

This server simply responds to two simple messages: one which requests a file listing and another which request file contents. Notice that the messages are distinguished by pattern matching, which works on atoms as well, such as list_dir.

-module(afile_server).
-export([start/1, loop/1]).

start(Dir) -> spawn(afile_server, loop, [Dir]).

loop(Dir) ->
{Client, list_dir} ->
Client ! {self(), file:list_dir(Dir)};
{Client, {get_file, File}} ->
Full = filename:join(Dir, File),
end,
loop(Dir).


The client simply serves to provide client-facing functions that abstract away the server protocol, i.e. the exact messages sent. These simply send the appropriate message and wait for the response.

-module(afile_client).
-export([ls/1, get_file/2]).

ls(Server) ->
Server ! {self(), list_dir},
{Server, FileList} ->
FileList
end.

get_file(Server, File) ->
Server ! {self(), {get_file, File}},
{Server, Content} ->
Content
end.


# Processes

spawn is an Erlang primitive that initiates a concurrent process and returns its identifier.

spawn(ModuleName, FuncName, [Arg1, Arg2, ..., ArgN])

% to spawn a process running the init function
% from the person module, i.e. person:init

spawn(person, init, ["Joe"])


The way in which processes can interact is through sending messages, which is done using the ! primitive.

RecipientPid ! Msg

% self() refers to the current process id

OtherProcess ! {self(), "Hey there"}


Processes are received in a receive block by pattern matching on the messages.

receive
{From, Message} ->
...
end


# Values

Values are bound with the = operator, like let in Haskell. It's also possible to pattern match on the value. Value names start with capital letters. Names beginning with lowercase letters are symbolic constants called atoms 1.

X = 123.


## Lists

Lists can be heterogeneous in Erlang.

1. Like Ruby :symbols and Scala 'symbols. ↩︎

February 26, 2014
18630dc — October 6, 2018