Share
Embed
Elixir di lunga vita.
Elixir è un linguaggio funzionale, che offre un approccio diverso rispetto alla programmazione a oggetti a cui siamo tutti abituati.
Durante la presentazione approfondiremo i punti di forza di Elixir, che lo rendono un linguaggio moderno e versatile e un'ottima soluzione per diversi tipi di applicazioni.
weLaika
July 04, 2016
Transcript
40 slides
-
BASIC TYPES i e x > 1 # i n
t e g e r i e x > 0 x 1 F # i n t e g e r i e x > 1 . 0 # f l o a t i e x > t r u e # b o o l e a n i e x > : a t o m # a t o m / s y m b o l i e x > " e l i x i r " # s t r i n g i e x > [ 1 , 2 , 3 ] # l i s t i e x > { 1 , 2 , 3 } # t u p l e -
ATOMS Atoms are constants where their name is their own
value Some other languages call these symbols i e x > : h e l l o : h e l l o i e x > : h e l l o = = : w o r l d f a l s e The booleans true and false are, in fact, atoms i e x > t r u e = = : t r u e t r u e i e x > i s _ a t o m ( f a l s e ) t r u e i e x > i s _ b o o l e a n ( : f a l s e ) t r u e -
LISTS Elixir uses square brackets to specify a list of
values i e x > [ 1 , 2 , t r u e , 3 ] [ 1 , 2 , t r u e , 3 ] i e x > l e n g t h [ 1 , 2 , 3 ] 3 -
++/2 AND --/2 OPERATORS i e x > [ 1
, 2 , 3 ] + + [ 4 , 5 , 6 ] [ 1 , 2 , 3 , 4 , 5 , 6 ] i e x > [ 1 , t r u e , 2 , f a l s e , 3 , t r u e ] - - [ t r u e , f a l s e ] [ 1 , 2 , 3 , t r u e ] HD/1 AND TL/1 i e x > l i s t = [ 1 , 2 , 3 ] i e x > h d ( l i s t ) 1 i e x > t l ( l i s t ) [ 2 , 3 ] -
TUPLES Elixir uses curly brackets to define tuples. Like lists,
tuples can hold any value i e x > { : o k , " h e l l o " } { : o k , " h e l l o " } i e x > t u p l e _ s i z e { : o k , " h e l l o " } 2 -
ACCESSING A TUPLE ELEMENT PER INDEX OR GETTING THE TUPLE
SIZE i e x > t u p l e = { : o k , " h e l l o " } { : o k , " h e l l o " } i e x > e l e m ( t u p l e , 1 ) " h e l l o " i e x > t u p l e _ s i z e ( t u p l e ) 2 PUT AN ELEMENT AT A PARTICULAR INDEX IN A TUPLE WITH PUT_ELEM/3 i e x > t u p l e = { : o k , " h e l l o " } { : o k , " h e l l o " } i e x > p u t _ e l e m ( t u p l e , 1 , " w o r l d " ) { : o k , " w o r l d " } i e x > t u p l e { : o k , " h e l l o " } -
LISTS Are stored in memory as linked lists Accessing the
length of a list is a linear operation Updating a list is fast as long as we are prepending elements -
TUPLES Are stored contiguously in memory Get the tuple size
or access an element by index is fast Updating or adding elements to tuples is expensive -
MATCH OPERATOR i e x > a = 1 1
i e x > a + 3 4 the le -hand side is a variable and the right-hand side is an integer literal, so Elixir can make the match true by binding the variable a to value 1 -
i e x > a = 1 1 i e
x > 1 = a 1 i e x > 2 = a * * ( M a t c h E r r o r ) n o m a t c h o f r i g h t h a n d s i d e v a l u e : 1 -
PATTERN MATCHING WITH LISTS i e x > f i
r s t _ l i s t = [ 1 , 2 , [ 3 , 4 , 5 ] ] [ 1 , 2 , [ 3 , 4 , 5 ] ] i e x > [ a , b , c ] = f i r s t _ l i s t [ 1 , 2 , [ 3 , 4 , 5 ] ] i e x > a 1 i e x > b 2 i e x > c [ 3 , 4 , 5 ] i e x > s e c o n d _ l i s t = [ 1 , 2 , 3 ] [ 1 , 2 , 3 ] i e x > [ d , 2 , e ] = s e c o n d _ l i s t [ 1 , 2 , 3 ] i e x > d 1 i e x > e -
PATTERN MATCHING WITH FUNCTIONS Pattern matching isn’t limited to just
variables in Elixir, it can be applied to function signatures i e x > h a n d l e _ r e s u l t = f n . . . > { : o k , r e s u l t } - > I O . p u t s " y a d d a " . . . > { : e r r o r } - > I O . p u t s " b a d d a " . . . > e n d i e x > s o m e _ r e s u l t = 1 i e x > h a n d l e _ r e s u l t . ( { : o k , s o m e _ r e s u l t } ) y a d d a i e x > h a n d l e _ r e s u l t . ( { : e r r o r } ) b a d d a -
The pipe operator |> passes the result of an expression
as the first parameter of another expression SOME NESTED FUNCTIONS f o o ( b a r ( l o l ( b a z ( ) ) ) ) THE PIPE SYNTAX b a z ( ) | > l o l ( ) | > b a r ( ) | > f o o ( ) -
OTP is actually a bundle that includes Erlang, a database
(Mnesia), and an innumerable number of libraries It also defines a structure for your applications THERE IS A LOT TO LEARN -
SOME OTP DEFINITIONS OTP defines systems in terms of hierarchies
of applications An application consists of one or more processes These processes follow one of a small number of OTP conventions, called behaviors -
GENSERVER When we write an OTP server, we write a
module containing one or more callback functions with standard names init(start_arguments) handle_call(request, from, state) handle_cast(request, state) handle_info(info, state) terminate(reason, state) code_change(from_version, state, extra) format_status(reason, [pdict, state]) -
CREATE A NEW PROJECT $ m i x n e
w s t a c k * c r e a t i n g R E A D M E . m d * c r e a t i n g . g i t i g n o r e * c r e a t i n g m i x . e x s * c r e a t i n g l i b * c r e a t i n g l i b / s t a c k . e x * c r e a t i n g l i b / s t a c k * c r e a t i n g t e s t * c r e a t i n g t e s t / t e s t _ h e l p e r . e x s * c r e a t i n g t e s t / s t a c k _ t e s t . e x s -
lib/stack/server.ex d e f m o d u l e
S t a c k . S e r v e r d o u s e G e n S e r v e r # P u b l i c A P I d e f s t a r t _ l i n k ( s t a c k ) d o G e n S e r v e r . s t a r t _ l i n k ( _ _ M O D U L E _ _ , s t a c k , n a m e : _ _ M O D U L E _ _ ) e n d d e f p o p d o G e n S e r v e r . c a l l ( _ _ M O D U L E _ _ , : p o p ) e n d d e f p u s h ( v a l u e ) d o G e n S e r v e r . c a s t ( _ _ M O D U L E _ _ , { : p u s h , v a l u e } ) e n d . . . -
. . . # G e n S e r
v e r i m p l e m e n t a t i o n d e f h a n d l e _ c a l l ( : p o p , _ f r o m , [ h e a d | t a i l ] ) d o { : r e p l y , h e a d , t a i l } e n d d e f h a n d l e _ c a s t ( { : p u s h , v a l u e } , s t a c k ) d o { : n o r e p l y , [ v a l u e | s t a c k ] } e n d e n d -
An OTP GenServer is just a regular Elixir process The
GenServer behavior defines a message loop internally and maintains a state variable. That message loop then calls out to various functions that we define in our server module -
the Elixir way says not to worry much about code
that crashes; instead, make sure the overall application keeps running -
SUPERVISORS AND WORKERS An Elixir supervisor has just one purpose:
it manages one or more worker processes -
NEW PROJECT! let's create a new project with a supervisor
$ m i x n e w - - s u p s t a c k _ s u p * c r e a t i n g R E A D M E . m d * c r e a t i n g . g i t i g n o r e * c r e a t i n g m i x . e x s * c r e a t i n g c o n f i g * c r e a t i n g c o n f i g / c o n f i g . e x s * c r e a t i n g l i b * c r e a t i n g l i b / s t a c k _ s u p . e x * c r e a t i n g t e s t * c r e a t i n g t e s t / t e s t _ h e l p e r . e x s * c r e a t i n g t e s t / s t a c k _ s u p _ t e s t . e x s -
stack_sup/lib/stack_sup.ex d e f m o d u l e
S t a c k S u p d o u s e A p p l i c a t i o n d e f s t a r t ( _ t y p e , _ a r g s ) d o i m p o r t S u p e r v i s o r . S p e c , w a r n : f a l s e c h i l d r e n = [ # W o r k e r s a n d c h i l d s u p e r v i s o r s t o b e s u p e r v i s e d w o r k e r ( S t a c k S u p . S e r v e r , [ [ 1 , 2 , 3 ] ] ) , ] o p t s = [ s t r a t e g y : : o n e _ f o r _ o n e , n a m e : S t a c k S u p . S u p e r v i s o r ] S u p e r v i s o r . s t a r t _ l i n k ( c h i l d r e n , o p t s ) e n d e n d -
lib/stack_sup/supervisor.ex . . . d e f s t a
r t _ l i n k ( i n i t i a l ) d o r e s u l t = { : o k , p i d } = S u p e r v i s o r . s t a r t _ l i n k ( _ _ M O D U L E _ _ , i n i t i a l ) s t a r t _ w o r k e r s ( p i d , i n i t i a l ) r e s u l t e n d d e f s t a r t _ w o r k e r s ( s u p , i n i t i a l ) d o { : o k , s t a s h } = S u p e r v i s o r . s t a r t _ c h i l d ( s u p , w o r k e r ( S t a c k S u p . S t a s h , [ i n i t i a l ] ) ) S u p e r v i s o r . s t a r t _ c h i l d ( s u p , s u p e r v i s o r ( S t a c k S u p . S u b S u p e r v i s o r , [ s t a s h ] ) ) e n d d e f i n i t ( _ ) d o s u p e r v i s e [ ] , s t r a t e g y : : o n e _ f o r _ o n e e n d e n d -
lib/stack_sup/subsupervisor.ex d e f m o d u l e
S t a c k S u p . S u b S u p e r v i s o r d o u s e S u p e r v i s o r d e f s t a r t _ l i n k ( s t a s h _ p i d ) d o { : o k , _ p i d } = S u p e r v i s o r . s t a r t _ l i n k ( _ _ M O D U L E _ _ , s t a s h _ p i d ) e n d d e f i n i t ( s t a s h _ p i d ) d o c h i l d _ p r o c e s s e s = [ w o r k e r ( S t a c k S u p . S e r v e r , [ s t a s h _ p i d ] ) ] s u p e r v i s e c h i l d _ p r o c e s s e s , s t r a t e g y : : o n e _ f o r _ o n e e n d e n d