On Github etrepum / intro-to-erlang-2013
Distributed massively concurrent soft-realtime systems that do not stop.
Erlang was prototyped in Prolog:
% factorial.pl (Prolog) :- module(factorial, [factorial/2]). factorial(0, 1). factorial(N, F) :- N>0, N1 is N-1, factorial(N1, F1), F is N * F1.
% factorial.erl (Erlang) -module(factorial). -export([factorial/2]). factorial(0) -> 1; factorial(N) when N > 0 -> N * factorial(N - 1).
List comprehensions from Miranda (like Haskell)
-- Subsets.hs module Subsets (subsets) where subsets :: [a] -> [[a]] subsets [] = [[]] subsets (x:xs) = [(x:y) | y <- ys] ++ ys where ys = subsets xs
% subsets.erl
-module(subsets).
-export([subsets/1]).
subsets([]) ->
[[]];
subsets([X | Xs]) ->
Ys = subsets(Xs),
[[X | Y] || Y <- Ys] ++ Ys.
Pattern matching like ML
(* reverse.sml *)
fun reverse(l : 'a list) : 'a list =
reverse1(l, [])
fun reverse1(l : 'a list, acc : 'a list) =
case l of
[] => acc
| (x::xs) => reverse1(xs, x::acc)
% reverse.erl
-module(reverse).
-export([reverse/1]).
reverse(L) ->
reverse(L, []).
reverse(L, Acc) ->
case L of
[] -> Acc;
[X | Rest] -> reverse(Rest, [X | Acc])
end.
-module(merge_sort).
-export([merge_sort/1]).
% bottom-up merge sort
merge_sort([]) ->
[];
merge_sort(L) ->
iterate([[X] || X <- L]).
iterate([Xs]) ->
Xs;
iterate(Lists) ->
iterate(merge_lists(Lists)).
merge_lists([Xs, Ys | Rest]) ->
[merge2(Xs, Ys) | merge_lists(Rest)];
merge_lists(Lists) ->
Lists.
merge2(Xs=[X | _], [Y | Ys]) when X > Y ->
[Y | merge2(Xs, Ys)];
merge2([X | Xs], Ys) ->
[X | merge2(Xs, Ys)];
merge2([], Ys) ->
Ys.
# merge_sort.py
def merge_sort(lst):
if not lst:
return []
lists = [[x] for x in lst]
while len(lists) > 1:
lists = merge_lists(lists)
return lists[0]
def merge_lists(lists):
result = []
for i in range(0, len(lists) // 2):
result.append(merge2(lists[i*2], lists[i*2 + 1]))
if len(lists) % 2:
result.append(lists[-1])
return result
def merge2(xs, ys):
i = 0
j = 0
result = []
while i < len(xs) and j < len(ys):
x = xs[i]
y = ys[j]
if x > y:
result.append(y)
j += 1
else:
result.append(x)
i += 1
result.extend(xs[i:])
result.extend(ys[j:])
return result
Convenient bit syntax for parsing binary data
%% This parses a TCP packet header! << SourcePort:16, DestinationPort:16, SequenceNumber:32, AckNumber:32, DataOffset:4, _Reserved:4, Flags:8, WindowSize:16, Checksum:16, UrgentPointer:16, Payload/binary >> = Segment, OptSize = (DataOffset - 5)*32, << Options:OptSize, Message/binary >> = Payload, << CWR:1, ECE:1, URG:1, ACK:1, PSH:1, RST:1, SYN:1, FIN:1>> = <<Flags:8>>, %% Can now process the Message according to the %% Options (if any) and the flags CWR, …, FIN etc.
RAM footprint per unit of concurrency (approx)
1.3KBCounter ! {self(), {add, 1}},
receive
{Counter, {result, N}} ->
io:format("~p~n", [N])
end
%% Parse HTTP headers from Socket
headers(Socket, Request, Headers) ->
ok = inet:setopts(Socket, [{active, once}]),
receive
{http, _, http_eoh} ->
%% All of the HTTP headers are parsed
handle_request(Socket, Request, Headers);
{http, _, {http_header, _, Name, _, Value}} ->
headers(Socket, Request, [{Name, Value} | Headers]);
{tcp_closed, _} ->
exit(normal);
_Other ->
%% Invalid request
exit(normal)
after ?HEADERS_RECV_TIMEOUT ->
exit(normal)
end.
Connect to other nodes by name
(node1@res)1> net_adm:ping(node2@res). pong (node1@res)2> self(). <0.38.0> (node1@res)3> rpc:call(node2@res, erlang, self, []). <6943.43.0> (node1@res)4> nodes(). [node2@res] (node1@res)5> rpc:cast(node2@res, init, stop, []). true (node1@res)6> nodes(). []
Open Telephony Platform
Framework has little to do with telephony.this_is_an_atom 'also an atom'binary (contiguous array of bytes w/ O(1) slice)
<<1, 2, "bytes", 9999:64/little>>integer (unbounded), float (64-bit double)
1125899839733759 2.5ref (unique reference)
1> make_ref(). #Ref<0.0.0.30>
[1, 2, 3] = [1 | [2 | [3 | []]]]Tuples
{one, two, 3}
1> fun () -> ok end. #Fun<erl_eval.20.80484245> 2> fun erlang:self/0. #Fun<erlang.self.0>pid (process identifier)
1> self(). <0.35.0>port (port identifier, similar to pid)
1> erlang:open_port(
{spawn, "/bin/ls"}, []).
#Port<0.606>
true /= falsecharacters are integers, strings are lists
"abc" == [$a, $b | [99]]records are tuples
-record(foo, {bar}).
#foo{bar=1} == {foo, 1}
1> X = 1, X = 2. ** exception error: no match …Assignment is pattern matching! (_ is wildcard)
1> {[X], _} = {[foo], bar}, X.
foo
2> {X, Y} = {foo, bar}, Y.
bar
case date() of
{2013, 10, 31} ->
halloween;
{2013, 10, N} when N >= 11,
N =< 13 ->
rupy_conference;
_ ->
some_other_day
end.
first(), second(), third().Semicolon delimits clauses ("or")
case X of 1 -> one; 2 -> two; _ -> other_number end.Period ends the last clause (".")
simple_function() -> ok.
%% hello.erl
%% USAGE: hello:world().
-module(hello).
-export([world/0]).
world() -> io:format("hello world~n", []).
Slides
http://bob.ippoli.to/intro-to-erlang-2013/
Source
github.com/etrepum/intro-to-erlang-2013
bob@redivi.com
@etrepum