Učím většinou já, občasně (a formálně) taktéž Martin Mareš. Seminář se koná ve čtvrtek v 15:40 v S11.
Zápočet se dává za domácí úkoly (celkem za 10 bodů, kolik je teoretické maximum zatím není známo). Na každý domácí úkol bude čas do následující hodiny, kde si pravděpodobně ukážeme něco jako autorské řešení. Úkoly mi, prosím, zasílejte na email (pokud možno i s tou částí za +, je to tak správně a mě pomáhá automaticky to třídit; pokud mi chcete udělat opravdu radost, pak text/plain s dodržováním rozumných pravidel (taktéž trochu shrnutých mnou česky)). Celkový získaný počet bodů prozradím na požádání, není veřejně dostupný.
V případě jakýchkoliv problémů jsem k zastižení. Problémy je lepší řešit dříve, než později.
Mezi problémy samozřejmě patří i věci jako nejasnosti zadání, žádosti o radu, a podobně. Emailová komunikace je preferovaná před jinými, neboť má rozumnou historii.
Hlavním zdrojem, který doporučuji, je perldoc. Dalším dobrým zdrojem je číst kód jiných, hodně se ho najde např. na CPANu, ale tam je třeba dávat si pozor ‒ ne všechen kód tam je kvalitní a většina ho jsou „prasárny“ a jiné smetí.
Po troše úvodních keců jsem pověděl malinko o historii a vzniku perlu, trochu zmínil, jaký to má vliv na styl jazyka a tak.
Poté jsem přešel k základní syntaxi. Ukázali jsme si, jak používat proměnné, jak řídící konstrukce (if, unless, while, for (i když ten jen zběžně)). Taktéž byla zmíněna hora operátorů (ale pravděpodobně je budeme muset potkávat ještě častěji, aby se zažily).
Mezi praktickými ukázkami bylo klasické Hello, World! a pozdrav uživatele. Taktéž jsme si ukázali několik verzí největšího společného dělitele a demonstrovali na něm, jak fungují řídící proměnné.
Za domácí úkol jsou slíbeny 0-2 body, dle jeho délky (hodnotící funkci si ještě budu muset vytvořit, ale jednoduše, čím kratší, tím lépe).
Cílem je vypsat klasickou základoškolskou násobilkovou tabulku v rozsahu 0 až 10. Měla by být zarovnaná (s číslicemi vpravo ve sloupečku, jak to tak u čísel bývá estetické). Pokud někdo zvládne mít nejkratší řešení a ještě k tomu přidat mřížku, kouká z toho pro něj bod navíc.
Dnes jsme víceméně probrali seznamy a pole. Řekli jsme si, co to je, jaký mají vztah, jak takovou věc zvětšovat, zmenšovat, indexovat, vytvářet, měnit mu velikost (několika různými způsoby) a zjišťovat velikost.
Mezi ukázky patřily dva způsoby, jak se dají hledat prvočísla. Jeden byl pomocí síta (kde jsme v poli vyškrtávali) a druhý postupným dělením prvočísly pod odmocninu.
Tím jsme se dostali k pár novým řídícím konstrukcím (next, last, redo a continue ‒ goto je natolik šílené, že si ho necháme na jindy).
Pak jsme ještě v rychlosti prošli hashe (něco, co se indexuje řetězci a ne čísly). Asi si je příště ještě zopakujeme, nebo ukážeme, k čemu jsou dobré.
Úkolem je napsat quicksort. Ale pozor, bez rekurze (nesmíte si napsat svoji funkci a tu volat). Pro jistotu nesmíte vůbec psát funkce. Bodování je podobné, jako minulé, ale rozsah je 2-3 body. Tedy, i ten, kdo má nejdelší, má 2 body, nejkratší dokonce 3.
Na začátku jsme si zopakovali něco kolem hashů, ukázali řešení domácího úkolu z minule a kousek kódu na počítání počtů výskytů slov na vstupu.
Poté jsme se vrhli na reference, jakožto nástroj na tvorbu vícerozměrných polí a jiných šílených struktur (reference je něco jako obdoba ukazatele, ale vrací paměť sama). Zmínili jsme jak základní použití, tak i zkrácené zápisy indexování a vytváření anonymních struktur.
Nakonec jsme malinko naťukli funkce, předávání parametrů, jejich volání a to, že jsou to také něco jako proměnné ve svém vlastním namespace, jdou vytvářet anonymní (a poté fungují jako plnohodnotné a vychované lambda funkce).
První úkol se týká referencí. Datová struktura/hodnota existuje do té doby, dokud na ní kdekoliv v programu existuje reference. Napište memory leak ‒ věc, která „užere“ kousek paměti, zapomene na ni referenci/neukládá to nikde, ale ten kousek paměti se už nikdy po dobu běhu programu nevrátí. Toto je jednoduché, takže je to jen za jeden bod.
Druhý domácí úkol je malinko složitější. Máte řádky z zónového souboru (DNS), které vypadají takto:
doména TTL IN NS jmenonameserveru
Sloupečky jsou odděleny blíže nespecifikovaným množstvím blíže nespecifikovaných bílých znaků. Pokud ve čtvrtém sloupci není NS, tak je tento řádek nezajímavý.
K jedné doméně je obvykle více různých nameserverů, které ji poskytují. Takže každá doména má nějakou svoji „množinku“ nameserverů. Ale mnohé nameservery poskytují více, než jednu doménu a je mnoho poskytovatelů domén, kteří mají svoji množinku a na ní velkou bandu domén.
Otázkou je, která množinka je nejčastější.
Řádky na vstupu mohou být v libovolném pořadí.
Za tento úkol jsou 2 body.
Dnes byla dvě témata. První z nich byl vstupně výstupní systém. Zmíněno bylo, jak při čtení a výpisech použít jiný soubor. Taktéž jsme si představili funkce open (včetně možností komunikace s externím programem) a close.
Jako druhé jsme si ukazovali, co to jsou moduly, a to jak jejich použití, tak vytváření. Byl zmíněn Exporter jako možnost, jak dát funkce k dispozici.
Jako bonus byly zmíněné některé speciální proměnné ($!, $/, $? a podobně).
Cílem je napsat externí třídění. Bude v samostatném modulu, který exportuje funkci. Ta funkce přebere otevřený soubor, v něm budou řádky (nesetříděné). Vrátí opět otevřený soubor, v něm budou řádky, ale setříděné.
Mohou se hodit jednak modul File::Temp a jednak funkce seek.
Za úkol jsou 2 body, s tím že hezká řešení ocením půlbodem navíc.
Autorské řešení (které by on půlbod navíc určitě nedostalo).
Dnes jsme si ukázali jednu z nejvýraznějších vlastností perlu ‒ regulární výrazy (které vůbec nejsou regulární, ale to nikomu nebrání jim tak říkat z historických důvodů).
Ukázali jsme si základní syntaxi, jak to jde použít pro zjištění, že řetězec vypadá podle nějakého vzoru, k vykusování částí a k nahrazování.
Také jsme si ukázali některá z „šílenějších“ rozšíření. Malá oprava: lookbehind je (?^lt;=regex), ne (?<regex) jak bylo uvedeno na hodině. Všechny tyto a mnohé další (a často šílená) rozšíření lze najít v perldoc perlre (pozor, docela hutné čtení).
Dnes bych rád funkci, která načítá konfigurační soubor. Jejím výsledkem bude hash dvojic jméno-hodnota.
Základní formou zápisu je jmeno = hodnota, každá na jednom řádku. Mezery na začátku a konci řádku, či okolo = se nepočítají. Cokoliv za # je komentář. Ale jsou povolené i takovéto věci:
jmeno = hodnota
jmeno = " hodnota"
# Komentar
jmeno = hodnota\
na vice radcich
jmeno = " hodnota
na více
řádcích a s \"uvozovkami\"" jmeno = hodnota; dalsi = jina
jmeno = "toto # není komenář"
Za úkol jsou 2 body. V případě částečné implementace bude přidělen menší počet bodů (někde z intervalu [0, 2]).
Vzorové řešení je zde.
Hlavním tématem dnešní hodiny bylo objektové programování v perlu. Ukázali jsme si, jak fungují metody, třídy a dědičnost (a že je to celé jen trik s -> a bless). Samozřejmě je okolo ještě několik detailů (jako AUTOLOAD a DESTROY).
Poté jsme si ukázali pár zajímavých funkcí a konstrukcí:
Také jsme zmínili, jak probíhá kompilace modulu a fáze BEGIN a END.
Úkoly jsou dva, každý po dvou bodech, neboť bude jeden týden přestávka kvůli státnímu svátku.
Prvním je funkce, která dostane libovolné množství objektů a ty „zkříží“/sloučí do jednoho ‒ vytvoří objekt, který bude mít metody všech objektů a když se některá zavolá, bude se chovat tak, jako by byla volána na tom objektu, ze kterého pochází. Má povoleno tyto předané objekty „spotřebovat“ na výrobu nového.
Druhá funkce dostane objekt, jméno a referenci na funkci a tuto funkci přidá jako metodu tohoto objektu pod zadaným jménem (nebo vytvoří nový objekt, který se bude chovat jako ten starý, etc.).
Řešení najdete zde, druhý úkol je zde ve dvou verzích.
Zmínili jsme, že perl má dva druhy řetězců. Bytové, kde se uchovávají jen data a znakové, kde se bere i význam, tedy znaky (přesněji, unicodové codepointy). Každý řetězec má příznak, který je zač.
Řekli jsme si o use utf8;, které slouží k označení zdrojového kódu v kódování utf8. Také o vrstvách sedících na vstupně výstupních zařízeních, které se zapínají pomocí :utf8, či :encoding(jmeno-kodovani) u open a binmode.
Ukázali jsme si, jak funguje modul DBI, příkazy pro vytvoření spojení, co je to statement a jak ho použít či jak se vyhnout explicitnímu zacházení s ním a prostě jen získat data.
Samozřejmě byl zmíněn i způsob, jak se zcela vyhnout potřebě správně escapovat hodnoty předávané jako parametry ‒ otazníky ve statementu a předané zvlášť.
Řekli jsme si, jak zhruba funguje takové CGI, jaké jsou některé další možnosti (FastCGI, mod_perl). Ukázali jsme si malinko z možností modulu CGI (a zmínili, že je mnoho jiných, které umí podobné věci) a to jak si přečíst parametr, cookie, jak naformátovat kousek hlaviček či html (přestože to jde prostě vypsat, použití funkcí někdy bývá pohodlnější).
Úkolem je napsat něco jako wiki-slovník jako webovou aplikaci. Bude mít políčko na slovo a políčko kde se vybere směr překladu. Když se stiskne tlačítko, objeví se překlad. Pokud neexistuje, objeví se políčko na přidání překladu a po odsouhlasení se nová verze uloží (a daná dvojice bude dále používána oběma směry). Chci zdroják, ne ukázat tu aplikaci ;-).
Je za 2 body.
Jedno možné řešení lze nalézt zde.
Dnešním hlavním tématem bylo „jak dělat více věcí zároveň“.
Jako první jsme si ukázali poněkud pochybný a ne zcela funkční modul threads, s tím, že tato vlákna nesdílí žádná data. Pro sdílení slouží threads::shared.
V druhé části hodiny jsme probrali událostmi řízené programování a moduly AnyEvent, AnyEvent::Socket, AnyEvent::Handle a AnyEvent::Util.
Dnešním dvoubodovým cvičením bude napsat zjednodušenou verzi http serveru. Bude poslouchat na portu 80 a odpovídat na dotazy. Obvyklý dotaz bude vypadat nějak takto:
GET URL HTTP/1.1
Hlavička: hodnota
Hlavička: hodnota
URL bude jméno souboru a má být bráno relativně k aktuálnímu adresáři. Verze protokolu (zde 1.1) i hlavičky budou ignorovány. Obvyklá odpověď bude vypadat asi takto:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Nějaký text
Bude umět poskytovat soubory z disku (pokud nebudou spustitelné, lze použít příkaz file na zjištění content type) a pouštět CGI skripty. Měl by umět generovat chybu 404 (Not found), pokud soubor neexistuje.
V případě CGI skriptu, jednak pozor na to, že část URL začínající ? již nemá být brána jako jméno souboru. Skript bude spuštěn, v případě, že skončí s nenulovým návratovým kódem, bude nahlášena chyba 500 (Internal server error), pokud projde dobře, tak bude nahlášen kód, jaký skript udá v hlavičce Status:, pokud není přítomná, tak je považováno za 200. Server bude poskytovat skriptu následující proměnné prostředí:
Toto není kompletní seznam toho, co je protokolem HTTP nebo CGI požadované, takže při testování to může mírně „drhnout“. Ale v této formě se dá čekat, že to bude alespoň trochu fungovat.
Samozřejmě by si měl poradit s věcmi jako že klient umře, či že má několik požadavků najednou.
Nějaké řešení lze prohlédnout tady.
Dnešní hodinu vedl Martin Mareš a mluvil o perlu 6, jeho operátorech a syntaxi.
Domácí úkol, napsaný v perl6, má přečíst svůj vstup, rozdělí na slova a vypíše jejich četnosti, setříděné od nejčástějších.
Posílány mají být Martinovi, mě Cc.
Sice je jednoduchý, ale v trochu novém jazyce, tak bude také za 2 body.
Nastalo pokračování perlu 6. Ukazovaly se metaoperátory a hyper operátory (operátory nad operátory a podobná zvěrstva). Také se ukazovalo objektové programování, metatřídy, dva druhy dědičnosti, několik způsobů přetěžování funkcí.
Dnešním úkolem je napsat (slušně se chovající) quaterniony. Bylo by hezké, kdyby se chovaly tak krásně, jako se chovají komplexní čísla v perlu6, tedy aby šlo napsat 1+3i-2j+k (například), aby šly sčítat, převádět na text, a podobně.
Opět za dva body.
V první části hodiny byly probírané „drobky“, co zbyly z dřívějších hodin. Nejdříve jsme se podívali na tzv. „taint mode“, jakýsi paranoidní mód perlu, který nevěří ničemu, co přišlo od uživatele a nedovolí s takovými daty provádět nebezpečné operace (např. předat jako parametr funkce system).
Poté jsme přešli na uživatelská rozhraní. Napřed jsme si ukázali knihovnu Curses, která umožňuje umísťovat text na libovolné místo terminálu a vytvářet okénka (a dělat barvičky a podobné šílenosti).
Jako další jsme si ukázali něco grafičtějšího ‒ knihovnu Gtk2, umožňující hrát si s okénky a tlačítky.
Nakonec jsme přešli na rozhraní s jazykem C. Předvedli jsme si pár datových typů, které se v perlu používají a jak se s nimi manipuluje (především jsme se věnovali typu SV, který představuje skalární hodnotu). Nakonec jsme si předvedli, jak se v perlu volají funkce. Jak se celé toto využije bude vysvětleno na další hodině.
Prvním domácím úkolem je textový sníh. Na obrazovce (v terminálu) budou pomalu padat vločky ‒ znaky *. Samozřejmě by to mělo přežít i věci jako změnu velikosti terminálu.
Druhým je ořezávadlo diakritiky. Vypustí se na adresář a ze všechny soubory v něm přejmenuje tak, aby neobsahovaly diakritiku (takže ze šnek.jpg udělá snek.jpg.
Třetím je vybírátko záložek. Jako parametry dostane jméno souboru se jmény a hodnotami záložek (např. url) a program, který jimi bude krmit (například prohlížeč). Zobrazí okno, ve kterém budou v očíslovaném seznamu jména záložek. Dále bude možné zadat, kterou záložku člověk chce a to buď číslem, nebo částí názvu. Vybírátko poté spustí program a jako parametr mu předá hodnotu odpovídající záložky (a ukončí se). V případě zadání částí jména může nastat to, že neodpovídá žádná záložka (pak se program jen ukončí a nepustí nic), nebo že jich bude odpovídat více než jedna (poté jsou všechny hodnoty předané tomu stejnému programu „najednou“).
Každý úkol je po jednom bodu.
Ukazovali jsme si jazyk XS ‒ něco, čím se dají psát obaly/lepidla mezi kódem v perlu a v C či C++.
Také jsme si ukázali, jak použít perlový interpretter z jiného programu.
Představme si konfiguraci v perlu, např. takovouto:
$CONFIG{a} = 12;
$CONFIG{b} = 1 + 2;
$CONFIG{c} = "$CONFIG{a} + $CONFIG{b}\n";
Chtělo by se ji použít z Cčkového programu. Úkolem je implementovat dvě funkce (případně tři):
Úkol je to těžší, proto je za celé 3 body.
Příště už tu nebudu, učit bude Martin. Taktéž, nevím, kdy budu mít čas podívat se na domácí úkoly, za což se omlouvám, ale snad to bude brzy (určitě na ně nezapomenu úplně).