Sources
-
Dmytro Lytovchenko. BEAM Wisdoms.
http://beam-wisdoms.clau.se/en/latest/ -
http://erlang.org/faq/introduction.html
-
http://whyerlang.com/
-
https://en.wikipedia.org/wiki/Functional_programming
Websites
Sources
Videos
-
Robert Virding. Hitchhiker's Tour of the BEAM
https://www.youtube.com/watch?v=_Pwlvy3zz9M
Steve Vinoski. A Peek Inside Erlang's OTP
https://www.youtube.com/watch?v=_Pwlvy3zz9M
- Benjamin Tan Wei Hao. The Little Elixir & OTP Guidebook (Kindle Locations 1022-1026). Manning Publications. Kindle Edition.
- Thomas, Dave. Programming Elixir 1.2: Functional |> Concurrent |> Pragmatic |> Fun (Kindle Locations 7504-7507). Pragmatic Bookshelf. Kindle Edition.
Books
Conclusion
- BEAM is more like an OS rather than a VM
- Instances of BEAM can communicate natively to each other locally or within a network
- Process oriented architecture where every process is an Actor that communicates through message passing
- Processes are isolated one to another, can be linked and monitored
- OTP is the framework to build distributed system using Erlang
- Processes supervise one another in a Supervision Tree creating a self-healing system
Erlang Virtual Machine
Text
Bogdan/Björn's Erlang Abstract Machine (BEAM)

https://www.erlang.org/
Kaczmarczyk, James
Sakai, Christian
Resilient Distributed Nature of Erlang
"If Java is 'write once, run anywhere', then Erlang is 'write once, run forever'"
Joe Armstrong,
creator of Erlang
A Quick Introduction about Elixir

http://elixir-lang.org/
Basic Syntax
# Basic syntax
defmodule Example do
def add_one_to_one do
1 + 1
end
end
iex(2)> Example.add_one_to_one()
2
Execute a function add_one_to_one that is located in module Example.
The execution returns 2 as a result
Actor Concurrency Model
- Everything is a process
- Each process performs a specific task.
- To tell a process to do something, you need to send it a message. The process can reply by sending back another message.
- The kinds of messages the process can act on are specific to the process itself. In other words, messages are pattern-matched. Other than that, processes don’t share any information with other processes.
Process 101
Spawn a Process
defmodule SpawnExample do
def say_hi do
IO.puts "Hello!"
end
end
iex(2)> spawn(SpawnExample, :say_hi, [])
Hello!
#PID<0.91.0>
iex(3)> spawn_link(SpawnExample, :say_hi, [])
Hello!
#PID<0.93.0>
iex(4)> spawn_monitor(SpawnExample, :say_hi, [])
Hello!
PID<0.95.0>
Spawn another process. If this spawned process dies, the spawner process stays alive and unaffected.
Spawn another process. If this spawned process dies, the spawner process also dies.
Spawn another process. If this spawned process dies, the spawner process gets notified.
Process Message Passing
defmodule MessageExample do
def listen do
receive do
{:hello_cutie, from} ->
IO.puts """
Received :hello_cutie from
#{inspect(from)},
but not going to reply back.
"""
{:please_reply, from} ->
IO.puts """
Received :please_reply from
"#{inspect(from)}",
all right, I'll reply back.
"""
send(from, :what)
{:kill_yourself, from} ->
IO.puts """
Told to kill myself from
#{inspect(from)},
fine, I'll kill myself.
"""
Process.exit(self(), :kill)
end
end
end
iex(8)> spawned_pid = spawn(MessageExample, :listen, [])
#PID<0.113.0>
iex(9)> send(spawned_pid, {:hello_cutie, self()})
Received :hello_cutie from
#PID<0.90.0>,
but not going to reply back.iex(10)> send(spawned_pid, {:please_reply, self()})
Received :please_reply
from "#PID<0.90.0>",
all right, I'll reply back.
{:please_reply, #PID<0.90.0>}
iex(11)> receive do
...(11)> :what ->
...(11)> IO.puts "Got :what back"
...(11)> end
Got :what backiex(12)> send(spawned_pid, {:kill_yourself, self()})
Told to kill myself from
#PID<0.90.0>,
fine, I'll kill myself.
{:kill_yourself, #PID<0.90.0>}
iex(13)> Process.alive?(spawned_pid)
falseDistributed and Fault Tolerance
Fault Tolerance
- "Let it crash" philosophy, means delegating error detection and handling to another process and not coding too defensively
- Links set up bidirectional relationships between processes that serve to propagate exit signals when a crash happens in one of the progress
- Monitors set up a unidirectional relationship between processes so that the monitoring process is notified when a monitored process dies. Exit signals can be trapped by system processes that convert exit signals into normal messages. You implemented a simple supervisor process using processes and links.
Fault Tolerance
defmodule Juliet do
def listen_for_love_letter do
receive do
{:i_love_you, from} ->
send(from, :i_love_you_too)
{:lets_die_together, from} ->
Process.exit(self(), :kill)
{:do_my_math_homework, from} ->
1 / 0
end
end
enddefmodule Romeo do
def listen_for_reply do
receive do
:i_love_you_too ->
IO.puts "Yeah! she loves me too"
end
end
endiex(4)> my_pid = self()
#PID<0.96.0>
iex(5)> {juliet_pid, _} = spawn_monitor(Juliet, :listen_for_love_letter, [])
{#PID<0.106.0>, #Reference<0.0.4.146>}
iex(6)> juliet_pid
#PID<0.106.0>
iex(7)> send(juliet_pid, {:do_my_math_homework, self()})
{:do_my_math_homework, #PID<0.96.0>}
iex(8)>
18:03:10.576 [error] Process #PID<0.106.0> raised an exception
** (ArithmeticError) bad argument in arithmetic expression
process.exs:94: Juliet.listen_for_love_letter/0
nil
iex(9)> Process.alive?(juliet_pid)
false
iex(10)> Process.alive?(my_pid)
trueiex(2)> juliet_pid = spawn(Juliet, :listen_for_love_letter, [])
#PID<0.99.0>
iex(3)> send(juliet_pid, {:i_love_you, self()})
{:i_love_you, #PID<0.96.0>}
iex(4)> Romeo.listen_for_reply()
Yeah! she loves me tooiex(2)> self()
#PID<0.96.0>
iex(3)> juliet_pid = spawn_link(Juliet, :listen_for_love_letter, [])
#PID<0.100.0>
iex(4)> send(juliet_pid, {:lets_die_together, self()})
** (EXIT from #PID<0.96.0>) killedBEAM to BEAM Native Communication over Network
The Erlang VM, called Beam, is more than a simple interpreter. It’s like its own little operating system running on top of your host operating system.
It handles its own events, process scheduling, memory, naming services, and interprocess communication. In addition to all that, a node can connect to other nodes— in the same computer, across a LAN, or across the Internet— and provide many of the same services across these connections that it provides to the processes it hosts locally.
BEAM to BEAM Native Communication over Network
defmodule Alpha do
def start do
:global.register_name(:alpha, self())
end
def do_action do
send_message()
listen_for_report()
end
def send_message do
send(:global.whereis_name(:bravo), :is_area_clear)
end
def listen_for_report do
receive do
:area_clear ->
IO.puts "All area clear"
end
end
enddefmodule Bravo do
def start do
:global.register_name(:bravo, self())
end
def do_action do
listen_for_command()
end
def listen_for_command do
receive do
:is_area_clear ->
send_message()
end
end
def send_message do
send(:global.whereis_name(:charlie), :is_area_clear)
end
end
defmodule Charlie do
def start do
:global.register_name(:charlie, self())
end
def do_action do
listen_for_command()
end
def listen_for_command do
receive do
:is_area_clear ->
send_message()
end
end
def send_message do
send(:global.whereis_name(:delta), :is_area_clear)
end
enddefmodule Delta do
def start do
:global.register_name(:delta, self())
end
def do_action do
listen_for_command()
end
def listen_for_command do
receive do
:is_area_clear ->
send_message()
end
end
def send_message do
send(:global.whereis_name(:alpha), :area_clear)
end
endBEAM to BEAM Native Communication over Network
⇒ iex --sname alpha alpha.exs
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(alpha@Christian-Sakais-MacBook-Pro)1> Node.connect(:"br
avo@Christian-Sakais-MacBook-Pro")
true
iex(alpha@Christian-Sakais-MacBook-Pro)2> Alpha.start
:yes
iex(alpha@Christian-Sakais-MacBook-Pro)3> Alpha.do_action()
All area clear
:ok
iex(alpha@Christian-Sakais-MacBook-Pro)4>
⇒ iex --sname bravo bravo.exs
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(bravo@Christian-Sakais-MacBook-Pro)1> Node.connect(:"ch
arlie@Christian-Sakais-MacBook-Pro")
true
iex(bravo@Christian-Sakais-MacBook-Pro)2> Bravo.start
:yes
iex(bravo@Christian-Sakais-MacBook-Pro)3> Bravo.do_action()
:is_area_clear
iex(bravo@Christian-Sakais-MacBook-Pro)4>⇒ iex --sname charlie charlie.exs
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(charlie@Christian-Sakais-MacBook-Pro)1> Node.connect(:"
delta@Christian-Sakais-MacBook-Pro")
true
iex(charlie@Christian-Sakais-MacBook-Pro)2> Charlie.start
:yes
iex(charlie@Christian-Sakais-MacBook-Pro)3> Charlie.do_action()
:is_area_clear
iex(charlie@Christian-Sakais-MacBook-Pro)4>⇒ iex --sname delta delta.exs
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(delta@Christian-Sakais-MacBook-Pro)1> Node.list
[:"charlie@Christian-Sakais-MacBook-Pro",
:"bravo@Christian-Sakais-MacBook-Pro",
:"alpha@Christian-Sakais-MacBook-Pro"]
iex(delta@Christian-Sakais-MacBook-Pro)2> Delta.start
:yes
iex(delta@Christian-Sakais-MacBook-Pro)3> Delta.do_action(
)
:area_clear
iex(delta@Christian-Sakais-MacBook-Pro)4>We call an instance of BEAM over a network, a "Node"
Remote Method Invocation with BEAM
⇒ iex --sname boss job.exs
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(boss@Christian-Sakais-MacBook-Pro)1> Node.connect(:"worker@Christian-Sakais-MacBook-Pro")
true
iex(boss@Christian-Sakais-MacBook-Pro)2> func = fn -> IO.inspect(Node.self()) end
#Function<20.52032458/0 in :erl_eval.expr/5>
iex(boss@Christian-Sakais-MacBook-Pro)3> Node.spawn(:"worker@Christian-Sakais-MacBook-Pro", func)
:"worker@Christian-Sakais-MacBook-Pro"
#PID<12320.98.0>
iex(boss@Christian-Sakais-MacBook-Pro)4>⇒ iex --sname worker
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(worker@Christian-Sakais-MacBook-Pro)1> Node.list
[:"boss@Christian-Sakais-MacBook-Pro"]
iex(worker@Christian-Sakais-MacBook-Pro)2> self()
#PID<0.86.0>
iex(worker@Christian-Sakais-MacBook-Pro)3>
Send a local function to be invoked in other Node
Remote Method Invocation with BEAM
⇒ iex --sname boss
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(boss@Christian-Sakais-MacBook-Pro)1> Node.connect(:"worker@Christian-Sakais-MacBook-Pro")
true
iex(boss@Christian-Sakais-MacBook-Pro)2> Node.spawn(:"worker@Christian-Sakais-MacBook-Pro", Job, :work, [])
#PID<8967.95.0>
Boss told me, #PID<0.95.0>, to do work
iex(boss@Christian-Sakais-MacBook-Pro)3>⇒ iex --sname worker job.exs
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(worker@Christian-Sakais-MacBook-Pro)1>Tell other Node to execute its function
defmodule Job do
def work do
IO.puts "Boss told me, #{inspect self()}, to do work"
end
endOpen Telecom Platform (OTP)
- Initially used to build telephone exchanges and switches. Since these devices have the same characteristics we want from any large online distributed application, so OTP is now a general-purpose tool for developing and managing large systems.
- Solves common distributed system problems such as application discovery, failure detection and management, hot code swapping, and server structure.
OTP Features
- Debugger
- Supervisors
- GenServers
- GenEvent
- Mnesia
- Hot code reload
- etc
Supervision Tree

What is Erlang?
- Erlang is a functional, open source programming language purpose-built for developing applications on distributed systems.
- It was designed for writing applications that are
- scalable
- fault-tolerant
- distributed
- non-stop
- soft-realtime
Many companies use Erlang
- The largest user of Erlang is Ericsson, a multinational networking and telecommunications equipment and services company. Erlang is used in several large telecommunications systems.
- Facebook uses Erlang to write the Facebook chat backend.
- Whatsapp uses Erlang to write messaging applications for smart phones
What types of applications is Erlang suited for?
- Telecommunication systems
- Servers for Internet applications
- Database applications which require soft-realtime behavior
Why?
- Erlang provides a simple and powerful model for error containment and fault tolerance
- Concurrency and message passing are a fundamental to the language.
- Erlang contains a large collection of open source libraries called OTP (Open Telecom Platform) for creating distributed systems applications.
- Applications written in Erlang are often composed of hundreds or thousands of lightweight processes. Context switching between Erlang processes is typically one or two orders of magnitude cheaper than switching between threads in a C program.
- The Erlang runtime environment, a virtual machine called BEAM, allows code in a running system to be updated without interrupting the program, called hot-swapping
Some Characteristics of Erlang
Erlang Worldview
- Everything is a process
- Processes are strongly isolated
- Process creation and destruction is a lightweight operation
- Message passing is the only way for process to interact
- Processes have unique names
- If you know the name of a process you can send it a message
- Processes share no resources
- Error handling is non-local
- Processes do what they are supposed to do or fail
Characteristics of Functional Programming Languages
- Functional programming languages treat computation as the evaluation of mathematical functions and avoids state-changes and mutable data.
- In functional code, output of a function depends only on the arguments, so calling the same function twice with the same arguments returns the same result.
- It is a declarative paradigm, meaning programming is done with expressions or declarations, as opposed to statements which cause side-effects.
- Iteration over elements in a functional language is accomplished with recursion
Introduction to BEAM
- BEAM is a virtual machine to run Erlang
- BEAM acts as an interface to the outside world.
- It does so through the use of Ports and NIFs.
- Ports make the outside look like a process
- NIFs make the outside look like a function call
- It does so through the use of Ports and NIFs.
- Asynchronous communication
- Process isolation (meaning a process can crash and not disable the system)
- Lightweight
- soft-realtime (meaning there are time restraints, but it is okay to go over them)
Introduction to BEAM
- For symmetric multiprocessing, BEAM uses a number of schedulers.
- each scheduler is semi-autonomous. One scheduler is created per virtual machine thread.
- Many separate memory spaces
Erlang Virtual Machine
By Christian Sakai
Erlang Virtual Machine
- 439