Introducere la Elixir Lang
Publicat: 2015-02-27O introducere în limbajul de programare Elixir (și de ce îl iubesc)
Am scris un articol în urmă cu câteva luni în care vă prezentam Golang și de ce mi-a plăcut atât de mult. Deși încă îmi place, în ultima vreme m-am jucat cu o limbă nouă; Elixir. Am cumpărat cartea Programming Elixir și am urmărit-o până la capăt. Am ajuns deja să iubesc Elixir și sper să vă arăt de ce în acest articol.
În timp ce lucram pentru Couchbase cu câțiva ani în urmă, am fost foarte interesat de Erlang și sistemele distribuite. Pentru mine, Erlang este confuz. Când am văzut Elixir, mi-am dat seama imediat că mă gândeam la ceva bun. Elixir este detaliat ca un limbaj funcțional și concomitent care rulează pe VM Erlang.
Am auzit de multe ori, oameni spunând că Elixir este „Ruby for Erlang” etc. Această teorie nu este complet incorectă, dar, în mod realist, este în principal doar sintaxa lui Elixir care este influențată de Ruby, deoarece nu împărtășește. multe dintre aceleași constructe de programare. Este, desigur, similar în privința Erlang, fiind construit deasupra Erlang VM și oferindu-ne acces direct la primitivele Erlang în mod nativ.
Oricum, fără nicio ezitare, să ne scufundăm și să mergem mai departe cu niște Elixir.
Instalare
Dacă rulați pe OSX, instalarea este la fel de ușoară ca și utilizarea Homebrew:
~ brew update
~ brew install erlang
~ brew install elixir
Odată ce ați făcut acest lucru, ar trebui să puteți rula:
~ elixir -v
> Elixir 1.0.2
Acum Elixir este instalat corect, putem deschide un Elixir interactiv și ne putem juca cu câteva tipuri comune de bază.
Tipuri în Elixir
Porniți un Elixir REPL interactiv introducând
> iex
Variabile:
iex(1)> name = "rbin"
#=> "rbin"
Atomi:
În Elixir, un atom este o constantă în care numele este propria sa valoare.
iex(2)> :this_is_an_atom
#=> :this_is_an_atom
iex(3)> :my_atom == :atom
#=> false
Tupluri:
Folosim notația Curly Brace pentru a defini tuplurile. În Elixir, tuplurile sunt stocate imediat în memorie, ceea ce înseamnă că obținerea dimensiunii unui tuplu sau accesarea unui element tuplu este rapidă, dar actualizarea sau adăugarea elementelor este costisitoare, deoarece necesită copierea întregului tuplu în memorie.
iex(4)> tuple = {:hello, "world"}
#=> {:hello, "world"}
iex(5)> elem(tuple, 1)
#=> "world"
Liste:
În Elixir, listele sunt stocate în memorie, ca liste legate. Putem actualiza listele în mod trivial adăugând elemente înainte, dar adăugarea elementelor este mai costisitoare, deoarece trebuie să parcurgem întreaga listă pentru a ne da seama de dimensiunea acesteia.
iex(8)> list = [1, 2, :atom]
#=> [1, 2, :atom]
iex(9)> ["string"] ++ list
#=> ["string", 1, 2, :atom]
iex(10)> list ++ [31]
#=> [1, 2, :atom, 31]
Există funcții încorporate foarte utile pentru a fi utilizate cu liste, inclusiv obținerea Capului și Cozii unei liste.
iex(11)> hd(list)
#=> 1
iex(12)> tl(list)
#=> [2, :atom]
Funcții anonime:
În Elixir, funcțiile sunt cetățeni de primă clasă, ceea ce înseamnă că putem transmite funcții ca argumente altor funcții. Mai jos, vom defini o variabilă numită add care conține o funcție, pe care apoi o vom transmite ca argument la is_function/1 func .
iex(14)> add = fn a, b -> a + b end
#Function<12.90072148/2 in :erl_eval.expr/5>
iex(15)> add.(13, 31)
#=> 44
iex(16)> is_function(add)
#=> true
Organizarea proiectelor noastre (mix)
Elixir este livrat cu un instrument super util numit Mix. Mix este un instrument de compilare care ne permite să generăm, să organizăm, să compilam și să testăm foarte ușor proiectele noastre. De asemenea, ne ajută să gestionăm dependențele. (Întotdeauna un subiect delicat!) Pentru a crea un nou proiect cu Mix, pur și simplu facem următoarele:
~ mix new myapp --module MyApp
Acest lucru va crea un director numit myapp cu câteva fișiere în interior. De asemenea, va defini un modul MyApp în interiorul lib/myapp.ex .
* creating README.md
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/myapp.ex
* creating test
* creating test/test_helper.exs
* creating test/myapp_test.exs
Your mix project was created successfully.
You can use mix to compile it, test it, and more:
cd myapp
mix test
După cum putem vedea, obținem toate fișierele necesare pentru o structură de bază a proiectului. Cred că aceasta este una dintre cele mai frumoase caracteristici disponibile care sunt livrate cu Elixir. A avea instrumente de management de proiect este foarte util și o economie mare de timp.
Fișierul mix.exs este fișierul principal folosit pentru a configura proiectul nostru și a gestiona dependențele etc. Obținem un test/folder , în care putem scrie teste foarte asemănătoare cu rubin pentru proiectul nostru. Desigur, obținem un lib/folder , care conține fișierele sursă pentru proiectul nostru. Dacă rulăm mix test pe aplicația noastră, obținem următoarele:
$ mix test
Compiled lib/myapp.ex
Generated myapp.app
.
Finished in 0.04 seconds (0.04s on load, 0.00s on tests)
1 tests, 0 failures
Randomized with seed 543313
Concurență
La fel ca Erlang, Elixir folosește modelul „Actor” pentru concurență. Tot codul nostru rulează în interiorul Processes , iar aceste procese sunt izolate unele de altele. Putem realiza programe complet concurente în Elixir, generând procese și trimițând și primind mesaje între ele.
În Elixir, începem procesele utilizând funcția de spawn , care ia o altă funcție ca argument.
iex(1)> spawn(fn -> IO.puts 1 + 1 end)
#=> 2
#PID<0.55.0>
După cum puteți vedea, am generat un proces care a scos 1 + 1 și a returnat, de asemenea, ID-ul de proces. Returnarea acestui ID de proces este utilă, deoarece îl putem atribui unei variabile și îl putem folosi pentru a trimite mesaje procesului. Înainte de a face asta, trebuie să creăm un mecanism de primire pentru a obține mesajele pe care le trimitem procesului. (Putem merge mai departe și face acest lucru în sesiunea noastră Interative Elixir , rând cu rând.)
Odată ce am făcut asta, putem crea un proces care evaluează area_loop și să-l atribuim pid .
pid = spawn(fn -> Geometry.area_loop() end)
#=> #PID<0.40.0>
Putem apoi trimite mesaje către pid pe care codul nostru predefinit se va potrivi, în funcție de faptul dacă primește atomul :rectangle sau atomul :circle .
send pid, {:rectangle, 2, 3}
#=> Area = 6
# {:rectangle,2,3}
send pid, {:circle, 2}
#=> Area = 12.56000000000000049738
# {:circle,2}
Putem verifica pentru a vedea dacă procesele încă rulează folosind Process.alive? funcţie.
Process.alive?(pid)
#=> false
Concluzie
Nici măcar nu am zgâriat suprafața în acest blog. Există atât de multe funcții uimitoare în Elixir, sper că veți continua să le verificați singur. Am enumerat mai jos câteva resurse de învățare pentru a vă ajuta pe parcurs, dar înainte să vă îndreptați și să vă scufundați, iată câteva dintre lucrurile mele preferate despre Elixir:
- Era ușor de înțeles, cu o sintaxă asemănătoare rubinului și primitive asemănătoare Erlang
- Are o comunitate fantastică în spate
- Modelul său de concurență îmi este atât familiar, cât și foarte puternic
- Mixul este o mană cerească și economisește mult timp
- Elixir ne încurajează să documentăm totul
- Face construirea de aplicații distribuite un câmp de luptă mult mai puțin confuz
- Pot să văd Elixir mergând un drum lung.
Resurse
Câteva resurse pe care le-am găsit foarte utile în scurta mea perioadă de învățare a Elixir:
- http://elixir-lang.org/getting-started/introduction.html
- https://pragprog.com/book/elixir/programming-elixir
- https://teamgaslight.com/blog/the-best-resources-for-learning-elixir
- http://exercism.io
* Ieși și sorbi din acel Elixir! – @rbin *