scalaz-stream Radek Miček



Podobné dokumenty
VISUAL BASIC. Práce se soubory

Střední odborná škola a Střední odborné učiliště, Hořovice

PHP PHP je skriptovací programovací jazyk dynamických internetových stránek PHP je nezávislý na platformě

Univerzita Palackého v Olomouci Radek Janoštík (Univerzita Palackého v Olomouci) Základy programování 4 - C# 3.4.

Motivace. Vstup a výstup. Minimální komunikace. Motivace. ÚDPJ - Vstup a výstup. Ing. Lumír Návrat katedra informatiky, A

Střední odborná škola a Střední odborné učiliště, Hořovice

České vysoké učení technické v Praze. Fakulta Elektrotechniky XD39NUR. Semestrální práce. Ovládání videokonferencí pomocí mobilního telefonu

Pokročilé programování v jazyce C pro chemiky (C3220) Operátory new a delete, virtuální metody

Střední odborná škola a Střední odborné učiliště, Hořovice

Úvod do programování - Java. Cvičení č.4

Využití OOP v praxi -- Knihovna PHP -- Interval.cz

Jazyk C# (seminář 6)

MBI - technologická realizace modelu

Textové soubory. alg9 1

Vstupní požadavky, doporučení a metodické pokyny

Inovace a zkvalitnění výuky prostřednictvím ICT Základy programování a algoritmizace úloh Typové a netypové soubory

9 - Map/filter/reduce OMO. Ing. David Kadleček, PhD

Konečný automat. Jan Kybic.

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

SQL - trigger, Databázové modelování

Spark SQL, Spark Streaming. Jan Hučín

IB015 Neimperativní programování. Seznamy, Typy a Rekurze. Jiří Barnat Libor Škarvada

Spark SQL, Spark Streaming. Jan Hučín

Algoritmizace a programování

Základy programovaní 3 - Java. Unit testy. Petr Krajča. Katedra informatiky Univerzita Palackého v Olomouci. 26.,27.

Příklad aplikace Klient/Server s Boss/Worker modelem (informativní)

Principy OOP při tvorbě aplikací v JEE. Michal Čejchan

Univerzita Palackého v Olomouci Radek Janoštík (Univerzita Palackého v Olomouci) Základy programování 4 - C# 10.4.

Datové struktury. alg12 1

Výčtový typ strana 67

UJO Framework. revoluční architektura beans. verze

Funkcionální programování

Ukládání a vyhledávání XML dat

Formy komunikace s knihovnami

Zadání: TÉMA: Zápis algoritmu, čtení textového souboru, porovnání řetězců.

Jazyk C práce se soubory. Jan Hnilica Počítačové modelování 16

EVROPSKÝ SOCIÁLNÍ FOND. Úvod do PHP PRAHA & EU INVESTUJEME DO VAŠÍ BUDOUCNOSTI

IB015 Neimperativní programování. Organizace a motivace kurzu, programovací jazyk Haskell. Jiří Barnat

Obsah přednášky. programovacího jazyka. Motivace. Princip denotační sémantiky Sémantické funkce Výrazy Příkazy Vstup a výstup Kontinuace Program

Masarykova střední škola zemědělská a Vyšší odborná škola, Opava, příspěvková organizace

DUM 12 téma: Příkazy pro tvorbu databáze

1 - Úvod do platformy.net. IW5 - Programování v.net a C#

Střední odborná škola a Střední odborné učiliště, Hořovice

Operátory ROLLUP a CUBE

Jazyk C# - přístup k datům

Práce se soubory. Úvod do programování 2 Tomáš Kühr

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

Outdoor Expert. Uživatelský manuál. Verze aplikace: OutdoorExpert_Manual.docx 1 /

6. Příkazy a řídící struktury v Javě

Soubor jako posloupnost bytů

Programovací jazyky Přehled a vývoj

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

NPRG030 Programování I, 2010/11

DSL manuál. Ing. Jan Hranáč. 27. října V této kapitole je stručný průvodce k tvorbě v systému DrdSim a (v

Více o konstruktorech a destruktorech

Zápis programu v jazyce C#

III/2 Inovace a zkvalitnění výuky prostřednictvím ICT

Maturitní otázky z předmětu PROGRAMOVÁNÍ

NPRG030 Programování I, 2016/17 1 / :58:13

Programovací jazyky. imperativní (procedurální) neimperativní (neprocedurální) assembler (jazyk symbolických instrukcí)

Z. Kotala, P. Toman: Java ( Obsah )

1 Webový server, instalace PHP a MySQL 13

- jak udělat konstantu long int: L long velka = 78L;

Návrh a tvorba WWW stránek 1/14. PHP a databáze

TÉMATICKÝ OKRUH Softwarové inženýrství

Bottle -- příklad. Databáze. Testovací data. id Jedinečný identifikátor řádku: Bude typu INT s AUTO_INCREMENT a nastavíme ho jako primární klíč

Úvod do databázových systémů

1. Programování proti rozhraní

8 Třídy, objekty, metody, předávání argumentů metod

Pole a kolekce. v C#, Javě a C++

ANOTACE vytvořených/inovovaných materiálů

Programovací jazyk Haskell

PROGRAMOVÁNÍ V SHELLU

Střední odborná škola a Střední odborné učiliště, Hořovice

programátor vs. vývojář

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

Střední odborná škola a Střední odborné učiliště, Hořovice

Základní příkazy OS UNIX

Dědění, polymorfismus

Základy jazyka C# Obsah přednášky. Architektura.NET Historie Vlastnosti jazyka C# Datové typy Příkazy Prostory jmen Třídy, rozhraní

8. lekce Úvod do jazyka C 3. část Základní příkazy jazyka C Miroslav Jílek

Funkcionální programování. Kristýna Kaslová

ZAŘÍZENÍ PRO VZDÁLENÝ SBĚR A PŘENOS DAT FIRMWARE

Správa paměti. Karel Richta a kol. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze Karel Richta, 2016

Frilo Control Center správa projektů

Algoritmizace a programování

Lambda funkce Novinky v interfaces Streamy Optional - aneb zbavujeme se null. Java 8. Ondřej Hrstka

Informační systémy 2008/2009. Radim Farana. Obsah. Dotazy přes více tabulek

Tabulková data. budeme pracovat s CSV soubory položky oddělené středníkem, např.

Dalším příkladem může být například výstup dat na různá zařízení, souborů, grafických rozhraní, sítě atd.

Agenda. Smysl teoretických cvičení Klasifikace Obecná pravidla Bugzilla Klasické problémy Poznámky k jednotlivým pojmům Antipatterns Testování testů

Statické proměnné a metody. Tomáš Pitner, upravil Marek Šabo

PREPROCESOR POKRAČOVÁNÍ

Software602 Form Designer

Inovace a zkvalitnění výuky prostřednictvím ICT Základy programování a algoritmizace úloh Textové soubory

Programovací í jazyk Haskell

Programování jako nástroj porozumění matematice (seriál pro web modernivyuka.cz)

Koláčky, sezení. Martin Klíma

Program převod z desítkové na dvojkovou soustavu: /* Prevod desitkove na binarni */ #include <stdio.h>

PŘETĚŽOVÁNÍ OPERÁTORŮ

Transkript:

scalaz-stream Radek Miček

Obsah 1. Jednoduché zpracování proudů C# + standardní knihovna vs Scala + scalaz-stream 2. Použití knihovny scalaz-stream v naší aplikaci O naší aplikaci Architektura naší aplikace Příklad: Služba pro ukládání historie hovorů 3. Srovnání S aktory (známými z Erlangu) S líným vstupem (známým z Haskellu) 16. dubna 2014 2

1. Jednoduché zpracování proudů 16. dubna 2014 3

scalaz-stream Knihovna pro zpracování proudů dat Proud dat = posloupnost dat, kde data přicházejí postupně a může jich být i nekonečně mnoho. Společnost Spinoco knihovnu scalaz-stream používá a spoluvyvíjí https://github.com/scalaz/scalaz-stream 16. dubna 2014 4

Př.: Čtení souboru (C# TextReader) Zadání: Načíst prvních 100 řádek souboru. var result = new List<string>(); using (var r = File.OpenText("a.txt")) { int i = 0; var line = ""; while ((line = r.readline())!= null && i < 100) { result.add(line); i++; } } 16. dubna 2014 5

Př.: Čtení souboru (C# TextReader) Zadání: Načíst prvních 100 řádek souboru, jenž začínají slovem 'Spinoco'. var result = new List<string>(); using (var r = File.OpenText("a.txt")) { int i = 0; var line = ""; while ((line = r.readline())!= null && i < 100) { if (line.startswith("spinoco")) { result.add(line); i++; } } } 16. dubna 2014 6

C# TextReader Nepřehledný kód měli bychom oddělit filtrování a omezování počtu řádek Filtrování dle predikátu (např. řádka začíná slovem 'Spinoco') nebo omezování počtu vrácených řádek (např. 100 prvních řádek) jsou často požadované funkcionality. Mohly by tedy existovat funkce, jenž transformují daný TextReader např.: TextReader FilterLines(TextReader r, Predicate<string> p) nebo TextReader LimitLines(TextReader r, int n). Standardní knihovna však funkce pro transformaci TextReaderu neobsahuje (a počet metod ve třídě TextReader nijak neusnadňuje psaní vlastních). TextReader je pouze pro čtení textových proudů dat Proč se ale omezovat na znaky a řetězce? 16. dubna 2014 7

C# IEnumerable / Java Iterable Rozhraní pro procházení posloupností prvků. 16. dubna 2014 8

Př.: Čtení souboru (C# IEnumerable) Zadání: Načíst prvních 100 řádek souboru, jenž mají prefix 'Spinoco'. var result = File.ReadLines("a.txt").Where(line => line.startswith("spinoco")).take(100).tolist(); Obyčejné volání metod var result = (from line in File.ReadLines("a.txt") where line.startswith("spinoco") select line ).Take(100).ToList(); Speciální syntax připomínající SQL 16. dubna 2014 9

Rozbor: Čtení souboru (C# IEnumerable) Zadání: Načíst prvních 100 řádek souboru, jenž mají prefix 'Spinoco'. var result = File.ReadLines("a.txt").Where(line => line.startswith("spinoco")).take(100).tolist(); Kód je přehledný IEnumerable je obvykle líné Ale v tomto případě, se soubor otevře ihned Metoda ReadLines není líná (.NET Framework 4.5.1) viz http://referencesource.microsoft.com/#mscorlib/system/io/readlinesiterator.cs Metody Where a Take transformují IEnumerable 16. dubna 2014 10

Př.: Zápis souborů (C# IEnumerable) Zadání: Buď lines instance IEnumerable<string>. Do prvního souboru chceme zapsat všechny řádky z lines a do druhého souboru jen ty, které začínají slovem 'Spinoco'. File.WriteAllLines("a.txt", lines); File.WriteAllLines( "b.txt", lines.where(line => line.startswith("spinoco"))); lines čteme dvakrát 16. dubna 2014 11

Př.: Zápis souborů (C# IEnumerable) Zadání: Buď lines instance IEnumerable<string>. Do prvního souboru chceme zapsat všechny řádky z lines a do druhého souboru jen ty, které začínají slovem 'Spinoco'. using (var w1 = File.CreateText("a.txt")) using (var w2 = File.CreateText("b.txt")) { foreach (var line in lines) { w1.writeline(line); if (line.startswith("spinoco")) { w2.writeline(line); } } } lines čteme jen jednou, ale řešení už není přehledné 16. dubna 2014 12

Př.: Uvolňování zdrojů (C# IEnumerable) Zadání: Buď lines instance IEnumerable<string>. Chceme vypsat každý druhý prvek lines. using (var e = lines.getenumerator()) { for (e.movenext(); e.movenext(); e.movenext()) { Console.WriteLine(e.Current); } } Bez using by hrozilo, že zdroje alokované enumerátorem nebudou uvolněny. 16. dubna 2014 13

C# IEnumerable Přehledný kód pro čtení a filtrování Speciální podpora v kompilátoru (yield return a yield break) Nedostatečně řeší zápis Lze zlepšit Uvolňování zdrojů závisí na kázni programátora Lepší by bylo, kdyby knihovna byla navržena tak, aby nemohlo dojít k úniku zdrojů Typové systémy některých jazyků (ATS, Rust, ParaSail) umí pomoci Scala ani C# takový typový systém nemají 16. dubna 2014 14

Jak scalaz-stream řeší uvolňování zdrojů? 16. dubna 2014 15

Jak scalaz-stream řeší uvolňování zdrojů? Sama je alokuje i dealokuje 16. dubna 2014 16

Př.: Čtení souboru (scalaz-stream) Zadání: Načíst prvních 100 řádek souboru, jenž mají prefix 'Spinoco'. val result = io.linesr("a.txt").filter(_.startswith("spinoco")).take(100).runlog.run Výrazy io.linesr("a.txt") io.linesr("a.txt").filter(_.startswith("spinoco")) io.linesr("a.txt").filter(_.startswith("spinoco")).take(100) mají typ Process[Task, String], a proto jim budeme říkat procesy Proces je líný na rozdíl od IEnumerable to platí vždy Soubor se neotevře, dokud to není třeba Otevření souboru a načtení řádek je vynuceno voláním runlog.run Metody filter a take transformují proces 16. dubna 2014 17

Př.: Čtení souboru (scalaz-stream) Zadání: Načíst prvních 100 řádek souboru, jenž mají prefix 'Spinoco'. val result = io.linesr("a.txt").filter(_.startswith("spinoco")).take(100).runlog.run scalaz-stream var result = File.ReadLines("a.txt").Where(line => line.startswith("spinoco")).take(100).tolist(); C# IEnumerable 16. dubna 2014 18

Př.: Transformace řádků (scalaz-stream) Zadání: Načíst délky řádek v souboru. val result = io.linesr("a.txt").map(_.length).runlog.run map transformuje řádky pomocí dané funkce V našem příkladu je funkce: řetězec Typy výrazů délka řetězce io.linesr("a.txt") : Process[Task, String] io.linesr("a.txt").map(_.length): Process[Task, Int] 16. dubna 2014 19

Př.: Čtení dvou souborů Zadání: Soubor mesta.txt obsahuje hlavní města zemí ze souboru zeme.txt (ve stejném pořadí). Cílem je spárovat země s jejich hlavními městy a výsledek zapsat do jiného souboru. val result = io.linesr("zeme.txt").zip(io.linesr("mesta.txt")).runlog.run result je posloupnost dvojic země město zip kombinuje dva procesy dohromady Opakovaně: Přečte jeden prvek z prvního vstupu (např. zeme.txt), jeden prvek ze druhého vstupu (např. mesta.txt), vytvoří dvojici a pošle ji dál Oba soubory jsou automaticky otevřeny i uzavřeny 16. dubna 2014 20

Př.: Výpis souboru (scalaz-stream) Zadání: Vypsat řádky souboru. io.linesr("a.txt").to(io.stdoutlines).run.run io.stdoutlines je sink, který vypisuje příchozí řetězce jako řádky na standardní výstup Řádky do sinku posíláme metodou to Použitím metody to řádky zmizí v sinku, místo nich zůstane hodnota () typu Unit (typ Unit je něco jako typ void, ale na rozdíl od něj má jedinou hodnotu) Metoda run (první) ignoruje výstup procesu (na rozdíl od metody runlog, jenž výstup procesu ukládá a vrací) Proč používáme run místo runlog? 16. dubna 2014 21

Př.: Zápis souborů (scalaz-stream) Zadání: Buď lines instance Process[Task, String]. Do prvního souboru chceme zapsat všechny řádky z lines a do druhého souboru jen ty, které začínají slovem 'Spinoco'. def linesw(filename: String): Sink[Task, String] = io.filechunkw(filename).pipein(text.utf8encode) lines.observe(linesw("a.txt")).filter(_.startswith("spinoco")).to(linesw("b.txt")).run.run Metoda observe pošle řádky do sinku Na rozdíl od metody to řádky nezmizí (dále s nimi můžeme pracovat) linesw je sink, který zapisuje řádky do souboru (bohužel není součástí knihovny) 16. dubna 2014 22

Co knihovna scalaz-stream umí? Transfromace prvků map, collect, Filtrování filter, drop, take, dropwhile, takewhile, droplast Agregování reduce, fold, exists, forall, Kombinování procesů append, repeat deterministicky: pipe, zip, zipwith, tee, nedeterministicky: merge, wye, mergen, 16. dubna 2014 23

Co knihovna scalaz-stream umí? Bezpečná práce se zdroji linesr, filechunkr, filechunkw, resource, Odlišení procesů s vedlejšími efekty (pomocí Task) Process[Task, A], Sink[Task, A], Channel[Task, A, B], A další flatmap, intersperse, awakeevery, 16. dubna 2014 24

scalaz-stream vs C# IEnumerable scalaz-stream automatická alokace i dealokace zdrojů nedeterministické čtení z více vstupů lepší podpora zápisu odlišení procesů s vedlejšími efekty pomocí typových signatur větší množství funkcí pro skládání a transformace procesů C# IEnumerable speciální podpora v kompilátoru 16. dubna 2014 25

2. Použití knihovny scalaz-stream v naší aplikaci 16. dubna 2014 26

Naše vize Jedna aplikace pro různé komunikační kanály Telefonní hovory Chat E-mail SMS Sociální sítě Funkce Historie komunikace On-line monitoring Statistiky Rozdělování úkolů a plánování času 16. dubna 2014 27

Architektura naší aplikace Front end JavaScript, AngularJS, HTML5 Back end Scala, scalaz-stream, Play Apache Kafka, Apache Cassandra 16. dubna 2014 29

Hledáme nové kolegy 1. Vývojáře ve Scale 2. Vývojáře v JavaScriptu U nás se skutečně programuje funkcionálně Je možné pracovat na zkrácený úvazek Pro více informací pište na create@spinoco.com 16. dubna 2014 30

Back end Webový server + supervizor + služby Propojeno pomocí procesů z knihovny scalaz-stream Webový server autentizuje uživatele a jejich požadavky předává konkrétním službám Supervizor startuje služby, dohlíží na ně a v případě potřeby je restartuje Služba Umí obnovit stav po restartu Vstupem může být výstup jiných služeb 16. dubna 2014 31

Př.: Služba pro ukládání historie hovorů K událostem o telefonních hovorech doplňuje uživatele, ukládá je do databáze a poskytuje je dalším službám (např. pro výpočet statistik) Vstupy Události o telefonních hovorech Stav telefonů kdo je právě přihlášen na každém telefonu a od kdy (spojitý proces prvek načtený z procesu obsahuje aktuální stav telefonů, vždy je možné načíst prvek) 16. dubna 2014 32

Př.: Služba pro ukládání historie hovorů Párování událostí o hovorech s uživateli: val calleventswithuser = callevents.zip(phoneswithuser.continuous).map(finduserfromphonemap).through(pairfromhistory(finduser).onlyif(_.user.isempty)) callevents je proces událostí o hovorech phoneswithuser.continuous je spojitý proces s aktuálním stavem telefonů zip vytvoří proces dvojic (událost o hovoru, aktuální stav telefonů) finduserfromphonemap bere dvojici (událost o hovoru, aktuální stav telefonů) a pokud může, přiřadí události o hovoru uživatele through je jako map, ale navíc může provést vedlejší efekt (např. hledání v DB) finduser najde v databázi uživatele, který byl přihlášen na telefonu v daný čas pairfromhistory přiřadí uživatele z DB události o hovoru 16. dubna 2014 33

Př.: Služba pro ukládání historie hovorů Ukládání událostí o hovorech do databáze: calleventswithuser.observe(storeevent) storeevent je sink, jenž uloží událost o hovoru do databáze Pokud událost projde za observe, je garantováno, že je uložena v databázi 16. dubna 2014 34

Obnovení stavu služby po restartu Komunikace mezi službami je posílána přes Apache Kafku Apache Kafka je systém pro posílání zpráv Podobá se např. RabbitMQ, na rozdíl od něj však garantuje trvanlivost zpráv (při vhodném nastavení) tj. zprávy se neztratí, když zápis do Kafky uspěje Zprávy se publikují (zapisují) do tzv. topiců Publikováním je zprávě automaticky přiřazeno pořadové číslo (offset) Více služeb může publikovat do jednoho topicu Více služeb může číst z jednoho topicu (i zprávy s různými offsety) Stav služby se jednou za čas ukládá do databáze společně s offsety naposledy zpracovaných zpráv z Kafky 16. dubna 2014 35

Obnovení stavu služby po restartu Po restartu služby se načte poslední uložený stav služby z databáze společně s offsetem naposledy zpracované zprávy z Kafky Služba se připojí ke Kafce a začne číst z následujícího offsetu 16. dubna 2014 36

Výhody knihovny scalaz-stream Požadovaná funkcionalita se poskládá použitím jednoduchých a znovupoužitelných funkcí Kód je lépe čitelný Služby nezávisí na implementaci databáze nebo Kafky Služby ani neví, že používají Apache Cassandru nebo Apache Kafku při konstrukci dostávají obyčejné procesy Výrazně usnadňuje testování (např. lze snadno nasimulovat selhání procesu, ale je těžké nasimulovat selhání Kafky nebo Cassandry) Typy popisují kód 16. dubna 2014 37

3. Srovnání 16. dubna 2014 38

Aktory Aktor je objekt, jenž zprávy zpracovává sekvenčně Aktor přijímá zprávy, na základě přijatých zpráv mění svůj vnitřní stav, provádí vedlejší efekty a posílá zprávy jiným aktorům Služba by byla aktor, kdybychom aktory používali 16. dubna 2014 39

scalaz-stream vs aktory scalaz-stream Pull z procesu se čte, jen když je to třeba Procesy se lehce kombinují pomocí jednoduchých funkcí existující proces můžeme využít jako součást procesů, jenž vytváříme Procesy se automaticky starají o alokaci a dealokaci zdrojů Z typu procesu jde poznat jeho vstup, výstup a i to, zda provádí vedlejší efekty Aktory Push aktor běží a posílá zprávy dalším aktorům, i když třeba na žádné zprávy nečekají Některé implementace aktorů (Erlang, Akka, Orleans) mají zabudovanou podporu pro dohled nad aktory (supervizor) Většina implementací aktorů nevyužívá typový systém z typu aktoru typicky nejde poznat, zda aktor dělá vedlejší efekty nebo jaké zprávy posílá jiným aktorům 16. dubna 2014 40

Líný vstup v Haskellu Funkce readfile načte obsah souboru jako řetězec (tj. seznam znaků) Ve skutečnosti čtení souboru probíhá až při žádosti o vyhodnocení načteného řetězce Potíž je v tom, že soubor není možné zavřít Soubor se zavře po dočtení nakonec nebo ho uzavře GC Výhoda líného vstupu spočívá v tom, že se souborem je možné pracovat jako s obyčejným seznamem (což je velice pohodlné) Některým programům navíc nevadí, že soubor není uzavřen ihned 16. dubna 2014 41

Děkuji za pozornost!