Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Erlang

 Erlang

Duarte Duarte

May 13, 2015
Tweet

More Decks by Duarte Duarte

Other Decks in Programming

Transcript

  1. History 1986 • First version in Prolog 1990 • Added

    distribution 1997 • BEAM VM in C 1998 • Open sourced 2006 • SMP support Erlang Agner Krarup Erlang Ericsson Language
  2. Erlang (the language) • Functional • Strict evaluation • Dynamic

    typing • Concurrency oriented • Garbage collected • General-purpose language
  3. Data types Type Example Info Integer 1234 Not limited in

    size Float 1.234 64 bit Atom ok Not garbage collected Reference #Ref<0.0.0.59> nake_ref/0 Binary <<139, 123>> Sequence of bytes Pid <0.45.0> Process ID Port #Port<erl_val> open_port/2 Fun #Fun<erlang.length.1> First class function
  4. Collections Type Example List [1, 2, 3] Tuple {1, “two”,

    “three” String “Hello, world” Record #example{field = “Value”}
  5. Erlang (the language) Functional language Built with concurrency and distribution

    in mind Able to scale extremely well Capable of reloading code on the fly Declarative style of programming Easier way to build our distributed applications More time to focus on coding Less downtime
  6. Erlang Selling Points • Built in concurrency model • Fault

    tolerance • Soft realtime • Pattern matching • SMP support out of the box • Very simple language Weaknesses • Poor string manipulation facilities • Weird syntax • Steep learning curve • Relatively small community
  7. Functional • First class functions L = fun erlang:length/1. %

    #Fun<erlang.length.1> L([1]). % 1 call(F, Args) -> F(Args). % ok call(L, [1, 2]). % 2 get_length() -> fun erlang:length/1. % ok LL = get_length(). % #Fun<erlang.length.1> LL([1, 2, 3]). % 3
  8. Functional • Higher-order functions double(L) -> map(fun(X) -> 2*X end,

    L). add_one(L) -> map(fun(X) -> 1 + X end, L).
  9. Functional • Immutable data S = atom. > atom S

    = anotheratom. > exception error: no match of right hand side value anotheratom
  10. Functional • Tail call optimization %% Recursive approach len([]) ->

    0; len([_|T]) -> 1 + len(T). %% Iterative approach tail_len(L) -> tail_len(L,0). tail_len([], Acc) -> Acc; tail_len([_|T], Acc) -> tail_len(T,Acc+1).
  11. Functional • Pattern matching %% Without pattern matching (Most languages)

    function greet(Gender,Name) if Gender == male then print("Hello, Mr. %s!", Name) else if Gender == female then print("Hello, Mrs. %s!", Name) else print("Hello, %s!", Name) end %% With pattern matching (Erlang) greet(male, Name) -> io:format("Hello, Mr. ~s!", [Name]); greet(female, Name) -> io:format("Hello, Mrs. ~s!", [Name]); greet(_, Name) -> io:format("Hello, ~s!", [Name]).
  12. Message passing -module(ping_pong). -export([start/0, ping/2, pong/0]). ping(0, Pong_PID) -> Pong_PID

    ! finished, io:format("ping finished~n", []); ping(N, Pong_PID) -> Pong_PID ! {ping, self()}, receive pong -> io:format("Ping received pong~n", []) end, ping(N - 1, Pong_PID). pong() -> receive finished -> io:format("Pong finished~n", []); {ping, Ping_PID} -> io:format("Pong received ping~n", []), Ping_PID ! pong, pong() end. start() -> Pong_PID = spawn(ping_pong, pong, []), spawn(tut15, ping, [3, Pong_PID]).
  13. Actor model % Create a process and invoke the function

    web:start_server(Port, MaxConnections) ServerProcess = spawn(web, start_server, [Port, MaxConnections]), % Create a remote process and invoke the function % web:start_server(Port, MaxConnections) on machine RemoteNode RemoteProcess = spawn(RemoteNode, web, start_server, [Port, MaxConnections]), % Send a message to ServerProcess (asynchronously). % The message consists of a tuple % with the atom "pause" and the number "10". ServerProcess ! {pause, 10}, % Receive messages sent to this process receive a_message -> do_something; {data, DataContent} -> handle(DataContent); {hello, Text} -> io:format("Got hello message: ~s", [Text]); {goodbye, Text} -> io:format("Got goodbye message: ~s", [Text]) end.
  14. Fault tolerance and error recovery start_critic() -> spawn(?MODULE, critic, []).

    start_critic2() -> spawn(?MODULE, restarter, []). restarter() -> process_flag(trap_exit, true), Pid = spawn_link(?MODULE, critic, []), receive {'EXIT', Pid, normal} -> % not a crash ok; {'EXIT', Pid, shutdown} -> % manual termination, ok; % not a crash {'EXIT', Pid, _} -> restarter() end.
  15. Erlang vs Prolog • Erlang • Prolog -module(tut4). -export([list_length/1]). %

    function to return list length list_length([]) -> 0; list_length([_F|R]) -> 1 + list_length(R). :- module(tut4). :- export list_length/2. % predicate to return list length list_length([], 0). list_length([_F|R], L):- list_length(R, N), L is 1 + N.
  16. Erlang: Actors -module(counter). -export([run/0, counter/1]). run() -> S = spawn(counter,

    counter, [0]), send_msgs(S, 100000), S. counter(Sum) -> receive value -> io:fwrite("Value is ~w~n", [Sum]); {inc, Amount} -> counter(Sum+Amount) end. send_msgs(_, 0) -> true; send_msgs(S, Count) -> S ! {inc, 1}, send_msgs(S, Count-1). % Usage: % 1> c(counter). % 2> S = counter:run(). % ... Wait a bit until all children have run ... % 3> S ! value. % Value is 100000
  17. Scala: Actors class Counter extends Actor { var counter: Int

    = 0; def act() = { while (true) { receive { case Inc(amount) => counter += amount case Value => println("Value is "+counter) exit() } } } } object ActorTest extends Application { val counter = new Counter counter.start() for (i <- 0 until 100000) { counter ! Inc(1) } counter ! Value // Output: Value is 100000 }
  18. Chatroom Server Actor -module(server). -export([start/0]). start() -> spawn(fun() -> loop([])

    end). loop(Clients) -> process_flag(trap_exit, true), receive {From, connect, Username} -> link(From), broadcast(join, Clients, {Username}), loop([{Username, From} | Clients]); {From, send, Msg} -> broadcast(new_msg, Clients, {find(From, Clients), Msg}), loop(Clients); {'EXIT', From, _} -> broadcast(disconnect, Clients, {find(From, Clients)}), loop(remove(From, Clients)); _ -> loop(Clients) end. broadcast(join, Clients, {Username}) -> broadcast({info, Username ++ " joined the chat."}, Clients); broadcast(new_msg, Clients, {Username, Msg}) -> broadcast({new_msg, Username, Msg}, Clients); broadcast(disconnect, Clients, {Username}) -> broadcast({info, Username ++ " left the chat."}, Clients). broadcast(Msg, Clients) -> lists:foreach(fun({_, Pid}) -> Pid ! Msg end, Clients). find(From, [{Username, Pid} | _]) when From == Pid -> Username; find(From, [_ | T]) -> find(From, T). remove(From, Clients) -> lists:filter(fun({_, Pid}) -> Pid =/= From end, Clients).
  19. Chatroom Client Actor -module(client). -export([connect/2]). connect(Username, Server) -> spawn(fun() ->

    start(Username, Server) end). start(Username, Server) -> Server ! {self(), connect, Username}, loop(Server, Username). loop(Server, User) -> receive {send, Msg} -> Server ! {self(), send, Msg}, loop(Server, User); {new_msg, From, Msg} -> io:format("[~s's client] - ~s: ~s~n", [User, From, Msg]), loop(Server, User); {info, Msg} -> io:format("[~s's client] - ~s~n", [User, Msg]), loop(Server, User); disconnect -> io:format("[~s's client] - Disconnected~n", [User]), exit(normal); _ -> io:format("[~s's client] - Error - Unknown command~n", [User]), loop(Server, User) end.
  20. References and online resources http://learnyousomeerlang.com/ http://www.tryerlang.org/ Erlang Programming A Concurrent

    Approach to Software Development Francesco Cesarini, Simon Thompson Erlang and OTP in Action Martin Logan, Eric Merritt, and Reichard Carlson http://www.erlang.org/