Introduction to Erlang Eddy Caron 2013 M1. ENS-Lyon 1 Systèmes Distribués Eddy Caron Introduction to Erlang Piece of History 1982 – 1985 Experiments with programming of telecom using > 20 different languages. Conclusion: The language must be a very high level symbolic language in order to achive productivity gains ! (Leaves us with: Lisp , Prolog , Parlog ...) 1985 – 86 Experiments with Lisp, Prolog, Parlog etc. Conclusion: The language must contain primitives for concurrency and error recovery, and the execution model must not have back-tracking. (Rules out Lisp and Prolog). We must therefore develop our own language with the desirable features of Lisp, Prolog and Parlog, but with concurrency and error recovery built into the language. 1987 The first experiments with Erlang. 1993 Distribution is added to Erlang, which makes it possible to run a homgeneous Erlang system on a heterogeneous hardware. Decision to sell implementations Erlang externally. Separate organization in Ericsson started to maintain and support Erlang implementations and Erlang Tools. 2 Systèmes Distribués Eddy Caron Introduction to Erlang The Erlang Shell The Erlang Shell [ecaron@aspen bin]$ ./erl Erlang R15B02 (erts-5.9.2) [source] [smp:8:8] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.9.2 (abort with ^G) 1> 2+5. 7 2> (42+6)*33/4. 396.0 3> halt(). [ecaron@aspen bin]$ You can use Ctrl+c to break BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution 3 Systèmes Distribués Eddy Caron Introduction to Erlang Hello world ‘%’ starts a comment ‘.’ ends a declaration Every function must be in a module one module per source file source file name is module name + “.erl” ‘:’ used for calling functions in other modules 4 Systèmes Distribués Eddy Caron Introduction to Erlang Module and Functions A programming language isn't much use if you can just run code from the shell. [ecaron@aspen Erlang]$ cat mult2.erl -module(mult2). -export([double/1]). double(X) -> 2 * X. use it [ecaron@aspen Erlang]$ erl Erlang R15B02 (erts-5.9.2) [source] [smp:8:8] [async-threads:0] [hipe] [kernelpoll:false] Compilation is ok ! Eshell V5.9.2 (abort with ^G) 1> c(mult2). {ok,mult2} 2> mult2:double(6). 12 Systèmes Distribués 5 Eddy Caron Introduction to Erlang Numbers Regular numbers 123 -34567 12.345 -27.45e-05 #-notation for base-N integers 1> 16#ff. 255 $-notation for character codes (ISO-8859-1) 2> $A. 65 6 Systèmes Distribués Eddy Caron Introduction to Erlang Atoms Must start with lower case character or be quoted friday unquoted_atoms_cannot_contain_blanks ’A quoted atom with several blanks’ ’hello \n my friend’ Similar to hashed strings use only one word of data constant-time equality test 7 Systèmes Distribués Eddy Caron Introduction to Erlang Tuples Terms seprated by ‘,’ and enclosed in {} {123, bcd} {123, def, abc} {person, 'Jax', ’Teller'} {abc, {def, 123}, jkl} {} A fixed number of items (similar to structure or record in conventional programming languages) A tuple whose first element is an atom is called a tagged tuple 8 Systèmes Distribués Eddy Caron Introduction to Erlang Other Data Types Module:fun(Arg1,Arg2,… Argn) Functions Bin = <<Bin0,...>> Binaries 1> spawn(m, f, []). Process identifiers <0.51.0> References: A reference is a term which is unique in an Erlang runtime system, created by calling make_ref/0. Erlang values in general are called « terms » All terms are ordered and can be compared with ‘<’, ‘>’, ‘==’, ‘=:=’ , etc. Systèmes Distribués Eddy Caron Introduction to Erlang 9 Recursive Functions Variables start with upper-case characters ‘;’ separates function clauses ‘,’ separates instructions Variables are local to the function clause Pattern matching and guards to select clauses 10 Systèmes Distribués Eddy Caron Introduction to Erlang Recursive Functions recurs.erl -module(recurs). -export([fac/1]). fac(0) -> 1; fac(N) -> N * fac(N-1). Compile and run [ecaron@aspen Erlang]$ erl Erlang R15B02 (erts-5.9.2) [source] [smp:8:8] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.9.2 (abort with ^G) 1> c(recurs). {ok,recurs} 2> recurs:fac(6). 720 11 Systèmes Distribués Eddy Caron Introduction to Erlang Recursive Functions dblfunc.erl -module(dblfunc). -export([fac/1, mult/2]). fac(1) -> 1; fac(N) -> N * fac(N - 1). mult(X, Y) -> X * Y. Compile and run [ecaron@aspen Erlang]$ erl Erlang R15B02 (erts-5.9.2) [source] [smp:8:8] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.9.2 (abort with ^G) 1> c(dblfunc). {ok,dblfunc} 2> dblfunc:fac(4). 24 3> dblfunc:mult(dblfunc:fac(4),2). 48 Systèmes Distribués 12 Eddy Caron Introduction to Erlang Tail Recursion The arity is part of the function name Non-exported functions are local to the module mylists.erl -module(mylists). -export([reverse/1]). reverse(L) -> reverse(L, []). reverse([H|T], L) -> reverse(T, [H|L]); reverse([], L) -> L. > mylists:reverse([3,2,1]). [1,2,3] Systèmes Distribués 13 Eddy Caron Introduction to Erlang Tail Recursion > mylists:reverse([1,2,3]). [3,2,1] reverse([1,2,3]) -> reverse([1,2,3],[]). -> reverse([2,3],[1]) -> reverse([3],[2,1]) -> reverse([],[3,2,1]) -> [3,2,1] mylists.erl -module(mylists). -export([reverse/1]). reverse(L) -> reverse(L, []). reverse([H|T], L) -> reverse(T, [H|L]); reverse([], L) -> L. 14 Systèmes Distribués Eddy Caron Introduction to Erlang Recursion over Lists Pattern-matching selects components of the data ‘_’ is a “don’t care” pattern (not a variable) ‘[]’ is the empty list ‘[X,Y,Z]’ is a list with exactly three elements ‘[X,Y,Z|Tail]’ has three or more elements 15 Systèmes Distribués Eddy Caron Introduction to Erlang List Recursion with Accumulator The same syntax is used to construct lists Strings are simply lists of character codes Avoid adding data to the end of the list 16 Systèmes Distribués Eddy Caron Introduction to Erlang Built-in Functions Implemented in C All the type tests and conversions are BIFs Most BIFs (not all) are in the module “erlang” Many common BIFs are auto-imported (recognized without writing “erlang:...”) Operators (‘+’,’-’,’*’,’/’,...) are also really BIFs Described in the BIFS manual 17 Systèmes Distribués Eddy Caron Introduction to Erlang Built-in Functions Some examples 1> date(). {2012,10,23} 2> time(). {1,14,35} 3> length([1,2,3,4,5]). 5 4> size({a,b,c}). 3 5> atom_to_list(an_atom). "an_atom" 6> list_to_tuple([1,2,3,4]). {1,2,3,4} 7> integer_to_list(3412). "3412" 8> tuple_to_list({}). [] 18 Systèmes Distribués Eddy Caron Introduction to Erlang Standard Libraries Application Libraries Stdlib Kernel a. b. c. d. e. erlang code file inet os a. b. c. d. lists dict sets ... 19 Systèmes Distribués Eddy Caron Introduction to Erlang Expressions Boolean and/or/xor are strict (always evaluate both arguments) Use andalso/orelse for short circuit evaluation ‘==’ for equality, not ‘=’ Always use parentheses when not absolutely certain about the precedence 20 Systèmes Distribués Eddy Caron Introduction to Erlang Fun Expressions 1> Fun1 = fun (X) -> X+1 end. #Fun<erl_eval.6.39074546> 2> Fun1(2). 3 3> Fun2 = fun (X) when X>=5 -> gt; (X) -> lt end. #Fun<erl_eval.6.39074546> 4> Fun2(7). gt 21 Systèmes Distribués Eddy Caron Introduction to Erlang Pattern Matching Match failure causes run-time error Successful matching binds the variables but only if they are not already bound to a value previously bound variables can be used in a pattern a new variable can also be repeated in a pattern -module(pm). -export([mylength/1]). mylength([]) -> 0; mylength([_|T]) -> mylength(T) + 1. 22 Systèmes Distribués Eddy Caron Introduction to Erlang Case-switches Any number of clauses Patterns and guards, just as in functions ‘;’ separates clauses Use ‘_’ as catch-all Variables may also begin with underscore signals “I don’t intend to use this value” is_valid_signal(Signal) -> case Signal of {signal, _What, _From, _To} -> true; {signal, _What, _To} -> true; _Else -> false end. Systèmes Distribués Eddy Caron 23 Introduction to Erlang If-switches Like a case-switch without the patterns and the ‘when’ keyword Use ‘true’ as catch-all factorial(N) when N == 0 -> 1; factorial(N) when N > 0 -> N * factorial(N - 1). 24 Systèmes Distribués Eddy Caron Introduction to Erlang Switching If Pattern Matching factorial(N) -> if N == 0 -> 1; N > 0 -> N * factorial(N - 1) end. factorial(0) -> 1; factorial(N) -> N * factorial(N-1). When Case factorial(N) when N == 0 -> 1; factorial(N) when N > 0 -> N * factorial(N - 1). factorial(N) -> 1 case (N) of 0 -> 1; N when N > 0 -> N * factorial(N - 1) end. 25 Systèmes Distribués Eddy Caron Introduction to Erlang List and Tuple Processing List Processing BIFs List Processing Functions member(X,L) append(L1,L2) reverse(L) delete_all(X,L) atom_to_list(A) float_to_list(F) integer_to_list(I) tuple_to_list(T) list_to_atom(L) ... hd(L) tl(L) length(L) Tuple Processing BIFS tuple_to_list(T) element(N,T) setelement(N,T,Val) size(L) … 26 Systèmes Distribués Eddy Caron Introduction to Erlang Catching Exceptions throw: user defined error: runtime errors exit: end process only catch throw exceptions normally -module(catch_it). -compile(export_all). % An example of throw and catch g(X) when X >= 13 -> ok; g(X) when X < 13 -> throw({exception1, bad_number}). % Throw in g/1 % Catch in start/1 start(Input) -> case catch g(Input) of {exception1, Why} -> io:format("trouble is ~w ", [ Why ]); NormalReturnValue -> io:format("good input ~w ", [ NormalReturnValue ] ) end. 8> c(catch_it). {ok,catch_it} 9> catch_it:start(12). trouble is bad_number ok 10> catch_it:start(13). good input ok ok 27 Systèmes Distribués Eddy Caron Introduction to Erlang Processes Code is executed by a process A process keeps track of the program pointer, the stack, the variables values, etc. Every process has a unique process identifier: PID Processes are concurrent Virtual machine layer processes Preemptive multitasking Little overhead (e.g. 100.000 processes) Can use multiple CPUs on multiprocessor machines 28 Systèmes Distribués Eddy Caron Introduction to Erlang Concurrency • Several processes may use the same program code at the same time – each has own program counter, stack, and variables – programmer need not think about other processes updating the variables 29 Systèmes Distribués Eddy Caron Introduction to Erlang Message Passing • “!” is the send operator – • Messages are sent asynchronously – • Pid of the receiver is used as the address The sender continues immediately Any value can be sent as a message echo.erl -module(echo). -export([start/0,loop/0]). start() -> spawn(echo, loop, []). loop() -> receive {From, Message} -> io:format("> echo: ~w Msg: ~w ~n", [self(), Message]), From ! Message, loop() end. Systèmes Distribués Eddy Caron 1> c(echo). {ok,echo} 2> Id=echo:start(), 2> Id ! {self(),hello}. > echo: <0.38.0> Msg: hello {<0.31.0>,hello} 30 Introduction to Erlang Message Queues • Each process has a message queue (mailbox) – • incoming messages are placed in the queue (no size limit) A process receives a message when it extracts it from the mailbox – need not take the first message in the queue 31 Systèmes Distribués Eddy Caron Introduction to Erlang Receive a Message • receive-expressions are similar to case switches – – – • patterns are used to match messages in the mailbox messages in the queue are tested in order only one message can be extracted each time Selective receive – – – Patterns and guards permit message selection receive-clauses are tried in order If no message matches, the process suspends and waits for a new message 32 Systèmes Distribués Eddy Caron Introduction to Erlang Receive with Timeout • A receive-expression can have an after-part – • can be an integer (milliseconds) or “infinity” The process waits until a matching message arrives, or the timeout limit is exceeded – soft real-time: no guarantees sleep(T)- process suspends for T ms. sleep(T) -> receive after T -> true end. suspend() - process suspends indefinitely. suspend() -> receive after infinity -> true end. 33 Systèmes Distribués Eddy Caron Introduction to Erlang Send and Reply • Pids are often included in messages (self()), so that the receiver can reply to the sender – • Message order – • If the reply includes the Pid of the second process, it is easier for the first process to recognize the reply The only guaranteed message order is when both the sender and the receiver are the same for both messages (first-in, first- out) Selecting Unordered Messages – Using selective receive, it is possible to choose which messages to accept, even if they arrive in a different order 34 Systèmes Distribués Eddy Caron Introduction to Erlang Starting Processes The “spawn” function creates a new process • The new process will run the specified function • – • The spawn operation always returns immediately The return value is the Pid of the “child” 35 Systèmes Distribués Eddy Caron Introduction to Erlang Ping Pong tut16.erl -module(tut16). -export([start/0, ping/1, pong/0]). ping(0) -> pong ! finished, io:format("ping finished~n", []); ping(N) -> pong ! {ping, self()}, receive pong -> io:format("Ping received pong~n", []) end, ping(N - 1). pong() -> receive finished -> io:format("Pong finished~n", []); {ping, Ping_PID} -> io:format("Pong received ping~n", []), Ping_PID ! pong, pong() end. start() -> register(pong, spawn(tut16, pong, [])), spawn(tut16, ping, [3]). 1> c(tut16). {ok,tut16} 2> tut16:start(). Pong received ping <0.39.0> Ping received pong Pong received ping Ping received pong Pong received ping Ping received pong ping finished Pong finished 36 Systèmes Distribués Eddy Caron Introduction to Erlang Process Termination • Process Termination A process terminates when: – it finishes the function call that it started with a. There is an exception that is not caught • All messages sent to a terminated process will be thrown away • Same Pid will not be used before long time 37 Systèmes Distribués Eddy Caron Introduction to Erlang Registered Processes • A process can be registered under a name • Any process can send a message to a registered process, or look up the Pid • The Pid might change (if the process is restarted and reregistered), but the name stays the same Pid = spawn(?MODULE, server, []), register(myserver, Pid), myserver ! Msg. 38 Systèmes Distribués Eddy Caron Introduction to Erlang Links and Exit Signals • Any two processes can be linked – • When a process dies, an exit signal is sent to all linked processes, which are also killed – • normal exit does not kill other processe If a process sets its trap_exit flag, all signals will be caught and turned into normal messages – – • Links are always bidirectionnal process_flag(trap_exit, true) Signal is turned into message {‘EXIT’, Pid, ErrorTerm} This way, a process can watch other processes 39 Systèmes Distribués Eddy Caron Introduction to Erlang Distribution • Running “erl” with the flag “-name xxx” – – starts the Erlang network distribution system Makes the virtual machine emulator a “node” (‘xxx@host.domain’) • Erlang nodes can communicate over the network (but must find each other first) • Possible to send a Pid from one node to another (Pids are unique across nodes) • You can send a message to any process through its Pid (even on another node) • You can run several Erlang nodes (with different names) on the same computer 40 Systèmes Distribués Eddy Caron Introduction to Erlang Connecting Nodes • Nodes are connected the first time they try to communicate • The function “net_adm:ping(Node)” is the easiest way to set up a connection between nodes – • returns “pong” or “pang” Send a message to a registered process using – “{Name,Node} ! Message” 41 Systèmes Distribués Eddy Caron Introduction to Erlang Running Remote Processes • Variants of the spawn function can start processes directly on another node • The module ‘global’ contains functions for – • registering and using named processes over the whole network of connected nodes setting global locks 42 Systèmes Distribués Eddy Caron Introduction to Erlang Ports:Talking to the Outside • Talks to an external (or linked-in) C program • A port is connected to the process that opened it • The port sends data to the process in messages • A process can send data to the port 43 Systèmes Distribués Eddy Caron Introduction to Erlang Conclusion Try Erlang in practical session… • … and send me your own conclusion • 44 Systèmes Distribués Eddy Caron Introduction to Erlang References • Special and greatful thanks to Franck Petit et Sebastien Tixeuil • http://www.erlang.org • http://en.wikibooks.org/wiki/Erlang_Programming • Use case pour normalien ;-) – – Un Caml Light Distribué [Elkamel Merah , Allaoua Chaoui] « … Pour l’extension concurrente de Caml Light nous proposons quelques primitives avec une sémantique très simple en utilisant le modèle du langage de programmation ERLANG. Le support de la création dynamique de processus et de la communication asynchrone entre processus sont les deux principales extensions du langage Caml Light. " 45 Systèmes Distribués Eddy Caron Introduction to Erlang