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