Erlang Tutorial — Part 1A

John J. Camilleri
TDA383/DIT390 Concurrent Programming
HT2016 LP1

Overview

Erlang

Resources

Syntax

Hello world

% file: foo.erl
-module(foo).
-export([hw/0]).

hw() ->
  Msg = "Hello world!\n",
  io:fwrite(Msg).

Typing is dynamic

Tuples

Case

P1 = {human, "John", "Camilleri", 30},
P2 = {dog, "Fluffy", 3},
% Age = 17, % enabling this leads to no match
case P1 of
  {human, _, _, Age} -> Age ;
  {dog, _, Age} -> Age * 7 ;
  _ -> unknown_age
end.

If

if
  Age > 18 -> adult ;
  Age > 0  -> minor ;
  true     -> invalid_age
end.

Lists

Strings

Tail recursion

sum([X1,X2,X3,X4]) == X1 + X2 + X3 + X4
sum([X1,X2,X3,X4]) == X1 + (X2 + X3 + X4)
sum([X1,X2,X3,X4]) == X1 + sum([X2,X3,X4])
sum([]) == 0; % base case
sum([X1|XS]) == X1 + sum(XS). %recursive case

List comprehensions

Functions are first-class objects

No loops for control flow

Quiz & break

In each case, say what the return value of the given expression will be.


Erlang Tutorial — Part 1B

Shared state

class Counter implements Runnable {

  private int x = 0;

  public void run () {
    x++;
  }

  public static void main (String[] args) {
    Counter c = new Counter();
    (new Thread(c, "thread1")).start();
    (new Thread(c, "thread2")).start();
  }

}

Message passing

Spawning

Receiving

spawn(fun() ->
  receive
    X -> io:fwrite("I received: ~p~n", [X])
  end
end).

Sending

Pattern matching in receiving

receive
  {greet, Name}         -> "Hello " ++ Name ;
  {function, Fun, Args} -> apply(Fun, Args) ;
  X                     -> io:fwrite("I received: ~p~n", [X])
end.
Msg = receive ... end,
io:fwrite(Msg)

Clients and servers

recv() ->
  receive
    ...
  end,
  recv().

Returning value to client

Server

recv() ->
  receive
    {Pid, greet, Name}         -> Pid ! "Hello "++Name ;
    {Pid, function, Fun, Args} -> Pid ! apply(Fun, Args) ;
    _ -> skip
  end,
  recv().

Client

Pid ! {self(), greet, "everyone"},
io:fwrite("Request sent~n"),
receive
  X -> io:fwrite("Server response: ~p~n", [X])
end

Check waiting messages

process_info(self(), messages)
process_info(self(), message_queue_len)

self() ! foo,
self() ! bar,
process_info(self(), messages),
receive X -> X end,
X,
receive X -> X end. % this blocks even though there's a message waiting

Server state

recv(N) ->
  receive
    ...
  end,
  io:fwrite("Server has handled a total of ~p requests~n", [N+1]),
  recv(N+1).

spawn(foo, recv, [0]). % 0 = initial value of server's state