Kouzlíme s Elixirem aneb úvod do funkcionálních čar
V minulém měsíci jsme společně s kolegy a kamarády pořádali funkcionálně zaměřený BlueberryMeetUp s názvem f(“Blueberry”) = “Happy coding”. Jedno z témat bylo “Kouzlíme s Elixirem aneb úvod do funkcionálních čar”, které jsem měl to potěšení prezentovat. Tento článek pokryje první část této přednášky. Dozvíte se základy jazyka Elixir, úvod do jeho historie, vysvětlení některých datových typů a hlubší průnik do spojového seznamu (Linked list). Tento článek je první ze série zaměřené na Elixir. V budoucnu se budete moci těšit na články zaměřené na Pattern Matching, OTP, testování nebo benchmarking. V úvodu bych ještě rád řekl, že do Elixiru pronikám poslední rok, proto budu rád za každou připomínku nebo komentář.
Historie (velmi stručně)
Elixir má počátky v roce 2012. Autorem je José Valim. Elixir je postavený na silných základech jazyka Erlang, který byl vytořen v osmdesátých letech ve firmě Ericsson k používání v telekomunikacích, kdy jedním z hlavních požadavků bylo, aby software zvládal velké množství, na sobě nezávislých, dotazů najednou. Toto nám umožňuje jedinečná virtuální mašina Erlangu, tzv. BEAM. Podstatná vlastnost je, že selhání jednoho procesu nemůže způsobit pád celého systému. Tato vlastnost je označována jako fault-tollerant. Spadlý proces můžeme poté snadno restartovat. S tím souvisí velké téma Erlangu/Elixiru, kterým je OTP. OTP je v podstatě sada modulů a nástrojů pro správu procesů, posílání zpráv mezi nimi nebo jejich monitoring. Dobrým příkladem těchto modulů jsou GenServer, Agent nebo Supervisor. Erlang se považuje za léty prověřený jazyk a používá ho nejenom Ericsson, ale i firmy jako Motorola, Amazon, Yahoo, WhatsUp nebo Facebook.
Použití
Elixir lze použít na stejné případy jako Erlang. Konkrétní případy použití jsem pro přesnost převzal z knihy The Little Elixir & OTP Guidebook od Benjamin Tan Wei Hao. Tuto knihu vřele doporučuji.
- Chat servers (WhatsApp)
- Game servers (Wooga)
- Web frameworks (Phoenix)
- Distributed databases (Riak and CouchDB)
- Real-time bidding servers
- Video-streaming services
- Long-running services/daemons
- Command-line applications
Elixir vs. Erlang
Erlang a Elixir se kompilují do stejného bytecodu. To znamená, že v Elixiru můžeme používat bez obav Erlangové funkce a knihovny. Elixir dále přináší přednosti moderního jazyka. Mezi tyto přednosti patří přehlednější syntaxe a velké množství modulů a metod obsažených již v jazyku. K dispozici je podrobná dokumentace, kde je podrobně popsán každý modul a každá funkce. Nesmím také zapomenout na propracovaný tooling, ke kterému se dostaneme hned na dalších řádcích.
Interactive shell
Příkazová řádka Elixiru byl první tool se kterým jsem se setkal a mohl si v něm vyzkoušet spustit jednoduché programy. Kdo z vás zná REPL (read-eval-print loop), nebude ničím překvapen. Tato příkazová řádka má také k dispozici nápovědu nebo zvýraznění kódu. Jak si nainstalovat elixir i s příkazovou řádkou naleznete zde.
Mix
Asi nejdůležitější nástroj, který potřebuje každý, kdo začíná s Elixirem, je mix. Mix se stará o generování nového projektu, build, instalaci závislostí, spouštění testů nebo formátování kódu.
Hex a Hexdocs
Knihovny jsou uloženy v balíčkovacím systému zvaném Hex. Dost tomu pomáhá možnost psaní spustitelných doctestů přímo ke kódu. Dokumentaci knihoven pak najdeme na adrese hexdocs. Za kvalitu dokumentace každého balíčku odpovídají již tvůrci.
Při začátcích práce v Elixiru jsem měl největší obavu z nezralosti jazyka, nedostatku knihoven a malé komunity. Nové verze přicházejí pravidelně každých 6 měsíců (leden, červenec). Poslední tři verze, které mohu posoudit, neobsahují žádné změny, které by způsobily přepisování celé aplikaci. Například v posledních dvou verzích bylo mimo opravu chyb přidáno vylepšené zobrazování chybových hlášení, helpery pro debugovaní, integrovaný formater kódu a možná se dočkáme propety based testingu v následující verzi 1.7. Jedná se o vlastnosti, na kterých již jazyk nestojí a pro mě to je jeden z indikátoru stability. Dalším takovým indikátorem je stále rostoucí komunita. Velice živá je komunikace na Slacku nebo na fóru. S tím souvisí i stále se zvyšující počet hotových knihoven. Nezaostávají ani konference. Kromě vlastní ElixirConf v Evropě a v USA se témata o Elixiru hojně objevují všude, kde se mluví o funkcionálním programování. Firmy, které Elixir používají, jsou společnosti jako Adobe, Lonely planet, Pinterest nebo Bet365 a jejich počet se stále zvyšuje. Celý seznam můžete najít zde.
Syntaxe
Syntaxe jazyku vám může na první pohled něco připomínat, ale na druhý pohled zjistíte, že….
….Elixir není Ruby!
Obrázek výše může vzbuzovat dojem podobné syntaxe Ruby. Elixir je však funkcionální, tedy základem jsou funkce a ne objekty. Tento přístup mění myšlení od malého kousku kódu až po celou aplikaci. Podle mého názoru je tento přístup často jednodušší v závislosti na případu použití. Mezi další rozdíly patří i přístup k datům, která jsou imutabilní.
Datové typy
Elixir disponuje základními datovými typy jako boolean, integer, float, string, charlist. K dispozici máte však i další datové typy, které nemusíte znát z vašeho jazyka. Podíváme se na některé z nich, konkrétně na atom, Keyword list, mapu, a nakonec na list a čím se odlišuje.
Atom je konstanta, kde její název zároveň reprezentuje i její hodnotu. V jiných jazycích můžeme tento typ najít pod názvem Symbol. Zápis je jednoduše dvojtečka a value.
S atomy velice souvisí datový typ Keyword list. Každý takový Keyword list obsahuje sadu key-value párů, kde key je vždy atom. Podstatnou vlastnosti je, že pořadí těchto párů je dané vývojářem a že klíče se mohou opakovat.
Typem, kde může být klíčem téměř cokoliv, je mapa. Pořadí klíčů není dané a nemohou se opakovat.
Zbývá nám ještě jeden podstatný typ a to list. Záměrně jsem si ho nechal až na teď. Jde konkrétně o Linked List. Pojďme se na něj podívat v příkladech.
Linked list
V Elixiru můžeme list deklarovat dvojím způsobem. První je klasický zápis, který najdeme ve většině programovacích jazyků. Druhý způsob zápisu nám ukazuje, jak Elixír reálně s listem pracuje. Každá položka listu odkazuje na následující položky jako na list položek. Jedná se o v podstatě o sekvenci. Pojďme si ukázat k čemu nám to může vůbec být.
Na obrázku níže vidíme využití head a tail. Díky spojovému seznamu jsme si vzali první položku z listu (head) a zbytek (tail). Nechci vám ukazovat, že by šlo o nějaký zázrak. Nicméně tato vlastnost nám umožňuje procházení listů pomocí rekurze, která je v Elixiru/Erlangu velmi dobře optimalizovaná. Jedná se o takzvanou Tail Call Optimization.
Spojovy seznam díky svým vlastnostem od nás vyžaduje přemýšlet, zda přidáváme položku na začátek nebo na konec. Přidání položky na začátek listu je velice rychlé. Přidaná položka odkazuje na ostatní položky, resp. list položek. Což nás zbavuje nutnosti procházet celý list při této modifikaci, protože jeho vlastnosti jsou lehce dosažitelné. Avšak přidání položky na konec listu může být drahá operace. Vlastnosti předcházejících položek\listů jsou ovlivněny. Proto dochází k nutnosti projít všechny předchozí položky, tím se doba přidaní bude zvyšovat lineárně s délkou listu. Na následujícím obrázku jsou vidět příklady jak rychlého, tak pomalého přidání položky do listu.
Práce s listem
Na závěr vám ukážu několik možností jak s listem pracovat. Příklady jsou z Modulu List a Enum.
List.first
List.flatten
Enum.map
Reduce
V tomto článku jsme si lehce představili Elixir, jeho syntaxi a ukázali především práci s listem. V příštím článku bych rád navázal a pokračoval s tématem Pattern Matching.