Text vychází z mé přednášky na květnovém Ruby srazu v Praze.

tl;dr

Problém se slidy

Od loňského roku jsem začal učit programování v Ruby na Fakultě informačních technologií ČVUT, v předmětu MI-RUB. Jestli mě na přednášení něco nebavilo, je to příprava materiálů. Bez ohledu na množství obrázků a jak moc to „zaobalíme,“ nevyhnutelně dojde na ukázky kódu.

Prezentační slidy pak slouží jednak jako vodítko pro přednášející, jednak jako reference pro studenty. Typicky sáhneme po nějakém „slideware“ typu PowerPoint, případně po LaTeXu, který se alespoň postará o obarvení kódu. Progresivnější přednášející si připraví prezentaci v prohlížeči třeba s Reveal.js, ještě lépe psanou v Markdownu – například s Remark.js. Jenže ať obarvíme kód sebelépe, neřeší to jeden zásadní problém.

Při učení se nového jazyka (a programování vůbec) mi připadá důležitá fáze experimentování, možnost spustit existující kód, upravit jej, pozorovat změnu chování, rozbít jej, zjistit proč to nefunguje atp. Statické slidy s ukázkami kódu od experimentování spíše odrazují; pokud si chci ukázky sám vyzkoušet nebo předvést jejich variaci, kód musím postupně zkopírovat do samostatného souboru nebo do interpreta (například IRB) – „ideálně“ je kód přes několik slidů s vnořenými bloky. V případě MI-RUB udržujeme část ukázek stranou. To znamená více práce s údržbou pro nás a ztrátu času s hledáním kódu pro studenty (nemluvě o porušení DRY).

REPL FTW!

Ve snaze najít lepší přístup k přednášení mě napadlo, zda by se řešení nemohlo skrývat v REPL – Read–eval–print–loop, tedy interaktivní shell pro jazyk, jako již zmíněný IRB pro Ruby. Kouzlo REPL spočívá ve velice krátké smyčce mezi vstupem a zpětnou vazbou: napíšu řádku kódu a vidím výsledek – nebo chybu. Je to mnohem přístupnější než tradiční práce s textovým editorem nebo IDE, kde jsou fáze psaní kódu a spouštění kódu striktně oddělené. Velice pěkně toho využívá stránka TryRuby, která spojuje lineární výklad s experimentováním v REPL pro výuku jazyka.

Některé programovací jazyky a prostředí používají REPL jako primární způsob interakce. Na SNM jsme tak vytvářeli analýzy v jazyce R. RStudio IDE funguje především jako velký REPL s pokročilou historií a náhledem na data. Naše analýzy v R však většinou byly jednoduché dávkové skripty pro které je tento způsob práce naprosto ideální.

Pro účely výuky má však REPL řadu nevýhod. Není úplně jednoduché se vrátit zpět a změnit starší definici; musím si ji najít v historii, upravit a znovu spustit. Velký problém je i reprodukovatelnost; schválně, jak si v IRB uložím do souboru to, co jsem napsal? Že jsem měl použít Pry? Výsledkem však bude stále jen neokomentovaný textový soubor s mými vstupy, který můžu spustit jako celek, nebo řádku po řádce. S přípravou materiálů to příliš nepomůže.

Potřebovali bychom zkombinovat interaktivitu REPL s přenositelností prezentace nebo textového dokumentu. Dobrá zpráva je, že řešení existuje – a matematici nemusí číst dál.

Notebook je kamarád

Zdá se, že vědci tento problém vyřešili už před více než dvaceti roky. V aplikacích pro symbolickou matematiku a vizualizace, jako je Maple nebo Mathematica, se pracuje s interaktivními dokumenty, tzv. worksheety nebo notebooky.

Mathematica logistic bifurcation

Notebook v aplikaci Wolfram Mathematica (zdroj)

Notebook se skládá z jednotlivých buněk (cells); do buňky zapíšu kus kódu, který spustím a výsledek se mi zobrazí pod buňkou. Funguje to podobně jako REPL, ale se všemi výhodami textového dokumentu. Můžu změnit libovolný kus kódu a ten opět spustit.

Navíc v buňkách nemusí být jen spustitelný kód – mohou být i textové, ať už se jedná o zformátovaný text nebo třeba nadpisy. Notebook se ukládá i s výsledky výpočtů, takže ho můžu sdílet dál, převést do jiného formátu nebo vytvořit interaktivní prezentaci. Skvělé na tom je, že mám jediný zdrojový dokument s textem, kódem i jeho výsledky, který můžu sdílet dál beze ztráty informací nebo interaktivity. A nepotřebuji dělat vědecké výpočty, jako je třeba vizualizace Batmanovy křivky, abych využil výhody, které mi notebook nabízí.

Maple i Mathematica jsou však proprietární aplikace – a docela drahé. Proto vznikly svobodné alternativy; například Sage, který poskytuje mj. rozhraní pro notebook v prohlížeči sagenb.

Sage však trpí dalším neduhem: je primárně navržený pro práci v Pythonu, společně s ekosystémem knihoven a rozšíření specifických pro Sage. Celý systém je úzce provázaný, takže používáme-li jiné jazyky, moc nám nepomůže.

IPython – univerzální notebooky

Sage se zaměřuje na výpočty a vizualizace, přičemž jako prostředek používá Python. Paralelně však na bázi Pythonu vznikl jiný projekt: IPython. Původním cílem bylo vytvořit lepší REPL, avšak postupem času vznikl jeden z nejpropracovanějších interaktivních shellů vůbec, který umí zobrazovat i vizualizace. Ale zatímco Sage od základu nabízí vše „all inclusive,“ IPython je čistý Python s podporou pro grafické formy výstupu. Podobně jako Sage také nabízí rozhraní pro práci s notebookem v prohlížeči – IPython Notebook.

Notebook v tomto případě představuje jeden ze tří standardních frontendů – vedle textového rozhraní a grafické Qt konzole. Frontend je striktně oddělený od výpočetního jádra, které od něj přijímá zprávy a vrací výsledky.

Notebook běží jako webserver a komunikuje s výpočetním jádrem; editor zároveň běží jako klientská aplikace v prohlížeči, která se serverem komunikuje přes websockets.

Oddělení jádra od frontendu může na první pohled vypadat jako samolibý overengineering, ale je to zcela zásadní výhoda IPythonu. Komunikace s jádrem probíhá pomocí ZeroMQ, takže jádro může klidně běžet na jiném stroji než frontend. Jader může být i více – IPython má podporu pro paralelní výpočty. Můžete tak ovládat výpočetní cluster přímo z pohodlí notebooku.

Pro nás je ovšem zásadní fakt, že výpočetní jádro nemusí být vůbec napsané v Pythonu. Alternativní jádra jsou vítaná a těší se stále lepší podpoře. Existuje například jádro pro Haskell, jádro pro jazyk Julia je dokonce oficiální součástí projektu Julia. A ano, existuje i jádro pro Ruby, obligátně nazvané IRuby.

Co je v notebooku

IPython notebook je soubor s příponou .ipynb. Jedná se o obyčejný JSON, ve kterém je jak obsah jednotlivých buněk, tak výstup spuštěného kódu. Příkazem ipython notebook (případně iruby notebook) se pak v aktuálním adresáři spustí webový server s editorem notebooku.

IRuby notebook

Buňky v dokumentu mohou být různých typů – kromě samotného kódu i bloky textu psané v Markdownu nebo nadpisy různých úrovní (pro lepší strukturování). Vedle toho může buňka nést i různá metadata – to se hodí především pro tvorbu prezentací (popisuji níže). Metadata buňky lze editovat přes Cell Toolbar.

Buňky s kódem můžu spustit dvojhmatem Ctrl+Enter. Rozhodující přitom není pořadí buněk v dokumentu, ale pořadí jejich spuštění – to indikují čísla nalevo od buňky. Definice si pamatuje aktuálně běžící jádro, takže pokud server mezitím restartuji nebo notebook otevřu na jiném počítači, je většinou dobré spustit všechny buňky v pořadí, v jakém jsou definovány. Tím, že buňky běží ve stejném kontextu, z nich lze postupně sestavit aplikace, které sahají přes několik tříd a metod.

Číslo nalevo od buňky označuje pořadí spuštění tak, jak si je pamatuje jádro.

Speciální funkce pro vizualizaci v noteboocích jsou nejlépe podporované v Pythonu (nepřekvapivě). IRuby se však v tomto směru začíná zlepšovat, takže s využitím dalších gemů je možné i v notebooku vytvářet elegantní grafy.

K čemu se notebooky nehodí

Notebooky jsou ideální na ukázku syntaxe a základních konstrukcí jazyka, případně na demonstraci jednoduchých aplikací. V některých případech se formát notebooku z principu nehodí.

U základních aplikací se často pracuje s přímým uživatelským vstupem z klávesnice (gets a podobně) – ten však v notebooku bohužel neumíme nasimulovat, takže příklady by s tím neměly pracovat.

Problém může nastat také u rozsáhlejších aplikací, například nad frameworkem Rails – notebook sice může načítat vnější závislosti, ale třeba webový server přímo z notebooku nejspíš nepoběží: jádro se zablokuje na vstupu ze socketu a nebude přijímat další příkazy. Leda by se spustilo v separátním vlákně… Na druhou stranu, zprovoznit konzoli Rails v IPython notebooku, to už je zajímavá výzva.

Velký problém mohou být i chyby v jádru jazyka. IRuby funguje tak, že nahrazuje některé standardní třídy (včetně třídy Kernel) vlastní implementací, která posílá výstupy zpět do notebooku. Občas se pak může stát, že v jádru zkrátka není implementovaná nějaká metoda, kterou nějaký gem používá. V takovém případě to chce klid a hlásit chyby.

Notebooky v praxi

Během prvního semestru jsem přepsal část přednášek z LaTeXu do formy notebooků a osvědčilo se mi to v několika směrech.

Příprava materiálů se stala mnohem pohodlnější. Mám jistotu, že ukázkový kód bude fungovat a bude vracet správný výstup. Navíc se v Markdownu pracuje mnohem lépe, než v LaTeXu.

Práce s výstupy je jednodušší. Když mám zdrojové materiály v LaTeXu, musím je upravit, vyexportovat do PDF (zpravidla ve více variantách), a ty nahrát na náš server pro podporu výuky. Zdrojový notebook verzuju ve veřejném repozitáři a kdokoliv si jej může zobrazit přes nbviewer, i pokud nemá nainstalovaný IPython. Jakmile dojde na prezentaci nebo jiný výstup, můžu jej zkonvertovat jedním příkazem do řady dalších formátů, včetně LaTeXu.

A v neposlední řadě, vše se rychleji upravuje a lépe se mi pracuje se zpětnou vazbou. Pokud si během přednášky někdo všimne chyby, padne zajímavý dotaz nebo nastane nějaká nejasnost, můžu chybu hned opravit, případně doplnit další kód, který problém lépe vysvětluje. Po přednášce pak změny jen uhladím a publikuju.

Po IRuby jsem sáhnul i na Rails Girls, kde jsme si v notebooku ukázali dědičnost tříd.

Nicméně já s IPythonem v podstatě teprve začínám. Například Eric Matthes používá IPython pro úvod do programování a C. T. Brown s ním učí evoluční biologii.


Jak na to

IPython a IRuby

  • Zprovozněte IPython Notebook alespoň verze 1.2 (aktuální je 2.1) – viz oficiální dokumentace.
  • Pro instalaci gemu je nutné mít správnou verzi knihovny ZeroMQ (alespoň 3.2) pro gem ffi-rzmq:
    • pod Debianem a Ubuntu buď balíček libzmq3-dev (pro kompilaci), nebo ruby-ffi-rzmq s libzmq3;
    • pod Windows (netestoval jsem) bude nutné nainstalovat ZeroMQ.
  • Gem nainstalovat přes gem install iruby.

Server se spouští příkazem iruby notebook v adresáři s notebooky. Chová se stejně jako příkaz ipython, ale pracuje se zcela izolovaným adresářem pro profily.

Prezentace s notebookem

Pro vytváření prezentací používám výše zmíněná metadata u buněk. Buňce nastavím příslušné chování (-/Slide/Subslide/Fragment/Skip/Notes), podle kterého se vygeneruje výsledná prezentace. Tím pádem mohu některé buňky z prezentace zcela vynechat a některé použít jako poznámky přednášejícího – názorně je to ukázané v tomto článku. Zkonvertovaný notebook pak bude používat Reveal.js. To má však jeden zásadní háček: vygenerovaná prezentace obsahuje opět jenom statické ukázky kódu, tím pádem celá anabáze za lepším přednášením ztrácí smysl.

Editor notebooků je jenom JavaScript, HTML a CSS, takže není problém jej rozšířit o další funkce. K tomu existuje celý repozitář notebook-extensions, konkrétně rozšíření slidemode, které umožňuje editor notebooku přepnout do režimu prezentace. Ta se potom chová podobně jako vyexportovaná prezentace (používá stejná metadata), ale všechny buňky je možné upravovat a spouštět.

Slidemode v prohlížeči

Systém rozšíření se však v IPythonu 2 změnil, takže současná rozšíření fungují zřejmě jinak. V mezičase nabízím svou verzi slidemode pro IPython 1.2.1, kompatibilní s profilem IRuby.

Třeba se časem dočkáme i oficiální podpory.


Další zdroje

Jiné nástroje a postupy

  • Beaker Notebook je alternativa IPython Notebooku od základu navržená pro podporu více jazyků. V současnosti je ve fázi betaverze a využívá část existujících jader pro IPython. Beaker existuje sotva půl roku, takže je příliš brzo činit závěry; určitě se však vyplatí sledovat jeho vývoj.
  • repl.it řeší REPL přímo v prohlížeči – interpret jazyka je zkompilovaný pomocí Emscripten do JavaScriptu.
  • Pro jazyk R existuje R Markdown, standardní Markdown dokumenty, kde se bloky kódu automaticky spustí. Z takových dokumentů je možné i generovat prezentace.
  • GitBook slouží primárně pro psaní interaktivních knih, ale také umožňuje vložit interaktivní kusy kódu – v současnosti je podporovaný JavaScript, ale podle autorů je plánovaná podpora Ruby i Pythonu.
  • Ještě pokročilejším nástrojem pro interaktivní knihy je Runestone Interactive, pod který spadá i web Interactive Python.
  • Zajímavé je využití notebooků pro ukázku API. Projekt RAML pro popis REST API nabízí API Notebook. Jedná se spíše o obecný notebook pro JavaScript s knihovnou pro import RAML.

Jiný přístup k notebooku

O IPythonu