Upload
serhiy-oplakanets
View
1.101
Download
5
Embed Size (px)
DESCRIPTION
Citation preview
Erlang IntroductionSerhiy Oplakanets, Lviv 2012
Friday, February 10, 12
Classification
• high-level
• general-purpose
• garbage-collected
• dynamically typed
• functional
• concurrent
Friday, February 10, 12
$ erlErlang R14B04 (erts-5.8.5) [source] [64-bit] [smp:4:4] [rq:4] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.8.5 (abort with ^G)1>
Friday, February 10, 12
Syntax
Friday, February 10, 12
Data Types
Friday, February 10, 12
1> 2 + 2.4
2> 3 * 5.15
3> 7 / 6.1.1666666666666667
Friday, February 10, 12
1> [].[]
2> [1, 2, 3].[1,2,3]
3> [101,104,63]."eh?"
Friday, February 10, 12
1> "a string"."a string"
2> [97,32,115,116,114,105,110,103]."a string"
Friday, February 10, 12
1> $H.722> $e.1013> $l.1084> $o.1115> [$H, $e, $l, $l, $o]."Hello"
Friday, February 10, 12
1> true.true2> false.false3> true == false.false4> false == false.true5> true /= false.true
Friday, February 10, 12
1> atom.atom
2> anotherAtom.anotherAtom
3> 'One more atom?'.'One more atom?'
Friday, February 10, 12
4> is_atom('One more atom?').true
Friday, February 10, 12
1> is_atom(true).true
2> is_atom(false).true
Friday, February 10, 12
1> {1,2,3}.{1,2,3}
2> {16, "hello"}.{16,"hello"}
3> {3.14, "Pi", {"foo", bar}}.{3.14,"Pi",{"foo",bar}}
Friday, February 10, 12
Invariable Variables
Friday, February 10, 12
1> Variable = "value"."value"
2> AnotherVariable = 128.128
Friday, February 10, 12
1> R = 5, Pi = 3.14.3.14
2> Pi.3.14
3> Pi * R * R.78.5
Friday, February 10, 12
1> X = 1.1
3> X = 2.** exception error: no match of right hand side value 2
4> X = 1.1?!?!
Friday, February 10, 12
Pattern Matching
Friday, February 10, 12
1> X = 1, Y = 1.12> X = Y.???
Friday, February 10, 12
1> UnboundVariable.* 1: variable 'UnboundVariable' is unbound
Friday, February 10, 12
1> X = 1.12> X.13> Y. * 1: variable 'Y' is unbound4> Y = 2.25> Y.2
Friday, February 10, 12
1> User = {"John", "Doe", 35}....2> {Name, Surname, Age} = User....3> Name."John"4> Age.35
Friday, February 10, 12
1> User = {"John", "Doe", 35}....2> {Name, Surname} = User.** exception error: no match of right hand side value {"John","Doe",35}
Friday, February 10, 12
2> User = {"John", "Doe", 35}....3> {Name, "Doe", 35} = User....4> Name."John"
Friday, February 10, 12
1> User = {"John", "Doe", 35}....2> {Name, _, Age} = User....3> Age.354> Name."John"
Friday, February 10, 12
1> _ = 1. 1
2> _.* 1: variable '_' is unbound
5> _ = 3.3
Friday, February 10, 12
1> [Head | Tail] = [1,2,3].[1,2,3]
2> Head.1
3> Tail.[2,3]
Friday, February 10, 12
1> [1 | [2 | [3]]].[1,2,3]
Friday, February 10, 12
Modules and Functions
Friday, February 10, 12
-module(test).-export([main/0]).
main() -> "Hello".
Friday, February 10, 12
1> test:main()."Hello"
Friday, February 10, 12
-module(test).-export([factorial/1]).
factorial(0) -> 1;factorial(N) -> N * factorial(N - 1).
Friday, February 10, 12
$ erlc test.erl $ erl ...1> test:factorial(3).62> test:factorial(5).120
Friday, February 10, 12
-module(logger).-export([log/1, log/2]).
log(Msg) -> {"info", Msg}.log(Level, Msg) -> {Level, Msg}.
--------------------8<--------------------
1> logger:log("Some info message.").{"info","Some info message."}2> logger:log("error", "Kernel panic!"). {"error","Kernel panic!"}
Friday, February 10, 12
log(Msg) -> log("info", Msg).log(Level, Msg) -> {Level, Msg}.
Friday, February 10, 12
Function Guards
Friday, February 10, 12
-module(test).-export([fib/1]).fib(0) -> 0;fib(1) -> 1;fib(N) when N > 0 -> fib(N-1) + fib(N-2).
Friday, February 10, 12
test:fib(0).03> test:fib(1).15> test:fib(8).216> test:fib(-23).** exception error: no function clause matching test:fib(-23)
Friday, February 10, 12
% Refactored factorial function:
factorial(0) -> 1;
factorial(N)when is_integer(N) and (N > 0) -> N * factorial(N - 1);
factorial(_) ->{error, "Invalid argument"}.
Friday, February 10, 12
7> factorial:factorial(3). 6
8> factorial:factorial(0).1
9> factorial:factorial(-1).{error,"Invalid argument"}
10> factorial:factorial("a").{error,"Invalid argument"}
Friday, February 10, 12
Concurrency
• any function can become a process
• process is a function executing in parallel
• process shares nothing with other processes
Friday, February 10, 12
Processes/Actors
• processes are extremely lightweight and fast
• ~15 seconds to spawn 100k processes on my machine (MacBook Pro 8.1, OSX)
Friday, February 10, 12
spawn(Module, Function, Arguments) -> Pid
Friday, February 10, 12
Any function can become a process
Friday, February 10, 12
8> io:format("Hello~n").
Hello
...
2> spawn(io, format, ["Hello~n"]).
Hello
...
Friday, February 10, 12
-module(actor).-export([loop/0]).
loop() -> receive die -> io:format("Exiting~n") end.
Friday, February 10, 12
2> Pid = spawn(actor, loop, []).<0.40.0>3> is_process_alive(Pid).true4> Pid ! die.Exitingdie5> is_process_alive(Pid).false
Friday, February 10, 12
loop() -> receive die -> io:format("Exiting~n"); Msg -> io:format("Got: ~p~n", [Msg]) end.
Friday, February 10, 12
2> Pid = spawn(actor, loop, [])....3> is_process_alive(Pid).true4> Pid ! "Hello".Got: "Hello"...5> is_process_alive(Pid).false
Friday, February 10, 12
loop() -> receive die -> io:format("Exiting~n"); Msg -> io:format("Got: ~p~n", [Msg]), loop() end.
Friday, February 10, 12
2> Pid = spawn(actor, loop, [])....3> Pid ! "Hello".Got: "Hello"4> is_process_alive(Pid).true5> Pid ! "Hello again!".Got: "Hello again!"6> is_process_alive(Pid).true7> Pid ! die.Exiting8> is_process_alive(Pid).false
Friday, February 10, 12
Processes are executed in parallel and share no
data
Friday, February 10, 12
-module(counter).-export([loop/1]).
loop(N) -> receive increment -> loop(N + 1); decrement -> loop(N - 1); print -> io:format("Current counter value: ~w~n", [N]), loop(N) end.
Friday, February 10, 12
2> Counter = spawn(counter, loop, [0])....3> Counter ! increment....4> Counter ! increment....5> Counter ! print. Current counter value: 2...6> Counter ! decrement....7> Counter ! print. Current counter value: 1
Friday, February 10, 12
2> C1 = spawn(counter, loop, [0]). <0.40.0>3> C2 = spawn(counter, loop, [10]).<0.42.0>
4> C1 ! increment, C1 ! increment, C1 ! print. Current counter value: 2
5> C2 ! decrement, C2 ! print. Current counter value: 9
Friday, February 10, 12
Distributed Erlang
Friday, February 10, 12
spawn(Node, Module, Function, Args) -> Pid
Friday, February 10, 12
1> spawn(DistributedNode, test, factorial, [10]).
Friday, February 10, 12
s erl -sname slave -setcookie '123!@#qwe'
...
(slave@Serhiys-MacBook-Pro)1> node().
'slave@Serhiys-MacBook-Pro'
Friday, February 10, 12
$ erl -sname master -setcookie '123!@#qwe'
...
(master@Serhiys-MacBook-Pro)1> net_adm:ping('slave@Serhiys-MacBook-Pro').
pong
(master@Serhiys-MacBook-Pro)3>spawn('slave@Serhiys-MacBook-Pro', factorial, factorial, [100]).
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
<6619.52.0>
Friday, February 10, 12
Fault Tolerance
Friday, February 10, 12
-module(actor).
-export([loop/0]).
loop() ->
receive
N ->
S = math:sqrt(N),
io:format("sqrt(~p) = ~p~n", [N,S]),
loop()
end.
Friday, February 10, 12
2> Pid = spawn(actor, loop, []).
...
3> Pid ! 4.
sqrt(4) = 2.0
...
5> Pid ! "a".
=ERROR REPORT==== 24-Jan-2012::14:06:02 ===
Error in process <0.40.0>
...
6> is_process_alive(Pid).
false
Friday, February 10, 12
Supervisors
• supervisors monitor processes and take actions on exit signals
• process linking does the trick
Friday, February 10, 12
start() -> spawn(actor, restarter, []).
restarter() ->
process_flag(trap_exit, true),
Pid = spawn_link(actor, loop, []),
register(myActor, Pid),
receive
{'EXIT', _Pid, _Reason} ->
io:format("Process crashed. Restarting~n"),
restarter()
end.
Friday, February 10, 12
2> actor:start().
3> myActor ! 4.
sqrt(4) = 2.0
4> myActor ! "foo".
Process crashed. Restarting
=ERROR REPORT====
Error in process <0.41.0> ...
5> is_process_alive(whereis(myActor)).
true
6> myActor ! 9.
sqrt(9) = 3.0
Friday, February 10, 12
Other great features
• Hot code loading
• OTP Framework
•
Friday, February 10, 12
Simplicity
• You just learned
• ~70% of Erlang syntax
• most major abstractions: modules, functions and processes
• most of the core data types
Friday, February 10, 12
Complexity
• Erlang/OTP is a complex framework
• Learning it takes time and practice
Friday, February 10, 12
Bad Stuff
• syntax
• Strings
• code organization
• libraries
• underestimated complexity of OTP and concurrent applications generally
• your colleagues will not understand you :)
Friday, February 10, 12
Practical Application
• Notable uses:
• Facebook (Chat)
• CouchDB
• RabbitMQ
• Membase
• Riak
Friday, February 10, 12
How to learn Erlang?
Friday, February 10, 12
http://learnyousomeerlang.com/
Friday, February 10, 12
http://www.erlang.org/doc/getting_started/intro.htmlErlang getting started guide:
Friday, February 10, 12
http://pragprog.com/book/jaerlang/programming-erlang
Programming Erlang: Software for a Concurrent World
Friday, February 10, 12
$ erl
Friday, February 10, 12
[$Q, $u, $e, $s, $t, $i, $o, $n, $s, $?].
Friday, February 10, 12
Thank you
Friday, February 10, 12