Hlavní navigace

Incanter: prostředí pro statistické výpočty s grafickým výstupem založené na Clojure

Pavel Tišnovský

Již jste se asi setkali s projektem R určeným zejména pro statistické výpočty. Jednou ze zajímavých alternativ k R je projekt Incanter, který je založen na Clojure a běží nad JVM. Díky tomu je poměrně snadno rozšiřitelný.

Doba čtení: 27 minut

11. Matice jako sekvence řádků

12. Základní operace s maticemi

13. Výpočet inverzní matice

14. Symbolické výpočty

15. Jednoduché grafy s průběhy funkcí

16. Zápis vzorců způsobem převzatým z LaTeXu

17. Uložení grafů do rastrových obrázků i do vektorového výkresu

18. Repositář s demonstračními příklady

19. Předchozí články o programovacím jazyku Clojure a jeho knihovnách

20. Odkazy na Internetu

1. Incanter: prostředí pro statistické výpočty s grafickým výstupem založené na Clojure

Na stránce www.clojure-toolbox.com, na níž se nachází nejužitečnější a samozřejmě taktéž nejpopulárnější knihovny a nástroje určené pro programovací jazyk Clojure, popř. pro ClojureScript, nalezneme mj. i nástroj nazvaný Incanter. Jedná se o skupinu knihoven pro Clojure, jejichž cílem je vytvořit rychlejší a rozšiřitelnější alternativu k nástroji a programovacímu jazyku R, který se používá v oblasti statistických výpočtů, vizualizace dat apod. Základní informace o nepochybně zajímavém projektu Incanter získáte ze slajdů prezentace Data Sorcery with Clojure & Incanter. V krátkém seriálu, který dnes (tímto článkem) začíná na Rootu vycházet, se postupně seznámíme jak se základními postupy, tak i se složitějšími příklady použití Incanteru (datové zdroje, kombinované grafy apod.)

Obrázek 1: Logo projektu Incanter.

Nástroj Incanter svým uživatelům nabízí zejména tyto funkce:

  1. Statistické funkce (nejenom ty základní, ale i poměrně pokročilé).
  2. Matematické funkce pro práci s vektory a maticemi.
  3. Podporu pro tvorbu různých typů grafů a pro vizualizaci dat.
  4. Export grafů do rastrových formátů popř. do vektorového formátu SVG.
  5. Funkce pro manipulaci s daty a s datovými zdroji (mj. i z Excelu atd.).
  6. Základní symbolické výpočty (prozatím je podporována symbolická derivace).
Poznámka: video Evolution of incanter (Gource Visualization) ukazuje postupný vývoj Incanteru, i když neobsahuje poslední změny verze, kterou si dnes popíšeme.

Obrázek 2: Snímek z videa.

2. Proč Incanter vznikl a z jakého důvodu by nás mohl zajímat?

Zajímavé a možná i poučné bude zjistit, z jakého důvodu vlastně projekt Incanter vznikl a proč by pro nás mohl být zajímavý, resp. proč použít Incanter a nikoli R, jazyk Julia či řešení založené na Pythonu). Hlavní motivací autorů tohoto projektu bylo vytvoření rozšiřitelné platformy určené pro statistické výpočty s umožněním vizualizace výsledků pomocí různých typů grafů. Tato platforma by měla uživatelům nabízet stejné či lepší vyjadřovací schopnosti než projekt R, ovšem s tím, že Incanter využije všech výhod aplikace běžící na virtuálním stroji Javy (JVM). Důvodem, proč je – minimálně slovy autorů – JVM vhodnou platformou, je mj. i to, že pro ni existuje prakticky nepřeberné množství knihoven určených pro načítání dat (použita je například knihovna xls), zpracování dat, jejich konverzi, prezentaci, přístupu k různým databázím (relační, dokumentové, objektové) atd. (ostatně přímo Incanter používá rozhraní k MongoDB pro serializaci svých datových struktur).

Obrázek 3: Incanter je alternativou ke známému nástroji R.

Nevýhodou běhu nad JVM oproti nativnímu kódu (ne oproti interpretu R!) jsou samozřejmě pomalejší výpočty, což se může negativně projevit při zpracování rozsáhlejších dat (nicméně zrovna v oblasti práce s homogenními maticemi je zpomalení přibližně „jen“ 10–20% oproti optimalizovanému Fortranu – výsledky benchmarků si uvedeme příště). Na druhou stranu je možné pro JVM použít například knihovnu Parallel Colt, která umožňuje některé výpočty provádět nativním kódem (BLAS, LAPACK, ARPACK, ATLAS atd.). Právě tato knihovna je v případě potřeby používána i systémem Incanter.

Poznámka: nutno doplnit, že dnes může být vhodnou platformou i ekosystém Pythonu, zejména při spojení možností knihoven Numpy, SciPy, Matplotlib, které lze popř. doplnit například knihovnou Pandas. Nicméně to je dosti rozsáhlé téma, které se zaslouží samostatný seriál :-), podobně jako samotný jazyk R.

Obrázek 4: V případě, že budete potřebovat použít jazyk R nad JVM, může vám pomoci projekt renjin (prozatím jsem nezkoušel, takže jen informuji o jeho existenci).

3. Nový programovací jazyk či „pouhá“ knihovna?

Po volbě platformy se autoři Incanteru zaměřili na další problém – jak vlastně uživatelům umožnit používat statistické funkce popř. funkce pro vykreslování grafů? V případě projektu R byl zvolen vlastní programovací jazyk s poměrně velkými vyjadřovacími schopnostmi, který navíc uživatele odstiňuje od nízkoúrovňových operací. V případ Incanteru je tomu jinak, protože se vlastně jedná o „pouhou“ knihovnu naprogramovanou v jazyku Clojure. Ovšem Clojure, jakožto homoikonický jazyk s podporou maker, může posloužit pro tvorbu DSL (doménově specifických jazyků), což znamená, že nad čistým Clojure si uživatelé mohou postavit další vrstvu a tu používat. Současně jim ovšem Clojure nabízí již výše zmíněnou možnost použití libovolné knihovny, která pro JVM vznikla (díky Java interop). Velká flexibilita Clojure je ostatně jedním z důvodů, proč není Incanter určen přímo pro Javu jakožto primárního jazyka pro JVM.

Obrázek 5: Incanter používá mj. i známou a užitečnou knihovnu JFreeChart.

Navíc volba lispovského jazyka, kterým Clojure i přes některé rozdíly nepochybně je, není pro oblast statistických výpočtů zcela nesmyslná, protože stále ještě existuje početná komunita používající dnes již vlastně prastarý systém Lisp-Stat (známý též jako XLispStat) popř. nástroje nad ním postavené, například program ViSTa nebo ARC. XLispStat, který měl velký vliv na celý obor vizualizací statistických dat, se používal a – což je zajímavé – stále ještě používá například v oblasti GIS, epidemiologie, astronomie atd. (to je ostatně velmi poučné – některé obory mohou být v oblasti IT resp. používaných nástrojů hodně konzervativní). A právě pro tuto komunitu může být projekt Incanter užitečný. Ostatně i samotný jazyk R byl Lispem ovlivněn, zejména ve svých počátcích.

Poznámka: pokud vás zajímají některé důvody pro použití lispovského jazyka v oblasti statistických výpočtů, přečtete si článek Back to the Future: Lisp as a Base for a Statistical Computing System (opět – jedná se o deset let starý článek, nicméně je stále validní, i když vlastně nediskutuje to hlavní – vlastní implementaci systému založeného na Lispu).
Mezi moderní přístupy k „array programming“ patří již zmíněný jazyk R, dále programovací jazyk Julia a samozřejmě též knihovna Numpy určená pro Python.

4. Instalace projektu Incanter

Na stránkách projektu Incanter nalezneme Java Archiv (jar), který obsahuje všechny potřebné knihovny a pro svou činnost vyžaduje pouze přítomnost JRE (Java Runtime Environment). Problém je, že tento archiv je založen na dnes již notně zastaralé verzi Incanteru, takže bude lepší si provést překlad a instalaci verze vlastní. Budete potřebovat Clojure (aspoň verze 1.7) a taktéž nástroj Leiningen; všechny další knihovny a nástroje se stáhnou automaticky při překladu.

Nejdříve naklonujeme celý repositář:

$ git clone https://github.com/incanter/incanter
 
Cloning into 'incanter'...
remote: Enumerating objects: 13863, done.
remote: Total 13863 (delta 0), reused 0 (delta 0), pack-reused 13863
Receiving objects: 100% (13863/13863), 41.45 MiB | 4.19 MiB/s, done.
Resolving deltas: 100% (8228/8228), done.
Checking connectivity... done.

Přejdeme do vytvořeného podadresáře:

cd incanter/

V případě některých verzí JVM je nutné nastavit proměnnou prostředí LEIN_JVM_OPTS tak, jak je to popsáno zde. Toto nastavení zajistí, že nástroj Leiningen bude schopen stáhnout všechny potřebné balíčky:

$ export LEIN_JVM_OPTS=-Dhttps.protocols=TLSv1.2

Následuje vlastní překlad, v jehož rámci se stáhnou potřebné knihovny a uloží se do podadresáře ~/.m2:

$ lein sub install
 
Reading project from modules/incanter-core
Retrieving org/clojure/spec.alpha/0.1.143/spec.alpha-0.1.143.pom from central
...
...
...
Retrieving swingrepl/swingrepl/1.3.0/swingrepl-1.3.0.jar from clojars
Created /home/tester/temp/out/xxx/incanter/./target/incanter-1.9.4-SNAPSHOT.jar
Wrote /home/tester/temp/out/xxx/incanter/./pom.xml
Installed jar and pom into local repo.

5. První spuštění interaktivního prostředí projektu Incanter

Incanter používá, podobně jako další projekty se stejným zaměřením, vlastní interaktivní smyčku REPL. Tu spustíme přímo z adresáře, kam byl naklonován repositář projektu:

$ cd incanter/

Nyní již můžeme interaktivní smyčku REPL spustit:

$ lein repl

Měla by se vypsat klasická uvítací obrazovka REPLu jazyka Clojure:

nREPL server started on port 52443 on host 127.0.0.1 - nrepl://127.0.0.1:52443
REPL-y 0.3.5, nREPL 0.2.6
Clojure 1.8.0
OpenJDK 64-Bit Server VM 1.7.0_79-b14
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

Dále můžeme otestovat, jestli jsou na CLASSPATH umístěny všechny důležité knihovny Incanteru:

(use '(incanter core stats charts))
nil

Pokud se skutečně vypíše pouze nil, znamená to, že knihovny je možné použít. Zkusme si tedy vykreslit například histogram náhodných hodnot s normálním rozložením:

(view (histogram (sample-normal 1000)))

Obrázek 6: Histogram náhodných hodnot s normálním rozložením.

Parametry histogramu jsou samozřejmě plně konfigurovatelné. Podrobnosti si řekneme příště:

(view (histogram (sample-normal 100000) :nbins 50 :title "Normální rozložení" :legend true :y-label "Četnost"))

Obrázek 7: Upravený histogram.

6. Infixová notace v lispovském jazyku aneb síla makrosystému jazyka Clojure

Incanter je sice knihovna (resp. skupina knihoven) určená pro programovací jazyk Clojure, který je založen na lispovské syntaxi volání funkcí, ovšem díky existenci makra $= je možné výrazy zapisovat i v infixové podobě, a to včetně správného vyhodnocení priorit operátorů. Podívejme se na několik příkladů.

Základní aritmetické operátory s vyhodnocením priorit:

incanter.irepl=> ($= 1 + 2)
3
 
incanter.irepl=> ($= 1 + 2 * 3)
7
Poznámka: operandy musíte oddělit mezerou, jinak dojde při expanzi makra k chybě.

Operátor pro umocnění se zapisuje pomocí dvojice hvězdiček:

incanter.irepl=> ($= 2 ** 10)
1024.0
 
incanter.irepl=> ($= 2 ** -4))
0.0625

Clojure se snaží při dělení celých čísel vyjádřit výsledek formou zlomku:

incanter.irepl=> ($= 10 + 20 * (4 - 5) / 6)
20/3

Zpracovat lze dokonce i vektory a matice (operátory jsou přetížené):

incanter.irepl=> ($= [1 2 3] + [4 5 6])
[5 7 9]
 
incanter.irepl=> ($= [1 2 3] * [4 5 6])
[4 10 18]
 
incanter.irepl=> ($= [[1 2][3 4]] + [[5 6][7 8]])
[[6 8] [10 12]]

Využití broadcastingu popsaného dále:

incanter.irepl=> ($= [1 2 3] + 10)
[11 12 13]
 
incanter.irepl=> ($= [1 2 3] * -1)
[-1 -2 -3]

Výsledky jsou typu:

incanter.irepl=> (type ($= [[1 2][3 4]] + [[5 6][7 8]]))
clojure.lang.PersistentVector
 
incanter.irepl=> (type ($= [1 2 3] * -1))
clojure.lang.PersistentVector

7. Matice jakožto základní datová struktura, s níž Incanter pracuje

Projekt Incanter je založen na zpracování (rozsáhlých) matic a tzv. datasetů. Ve skutečnosti však klasicky chápané matice v Clojure příliš podporovány nejsou. Při studiu základních knihoven Clojure lze dojít k závěru, že vlastně jen velmi málo funkcí a maker je určeno pro práci s těmito datovými typy, i když je samozřejmě možné jak vektory, tak i matice velmi snadno reprezentovat s využitím základních sekvenčních datových struktur Clojure – seznamů a vektorů. Ve skutečnosti to však není zcela ideální řešení, a to hned z několika důvodů, jejichž společným rysem je rychlost prováděných operací. Z tohoto důvodu je v případě implementace algoritmů, v nichž se intenzivně používají operace s maticemi, mnohem výhodnější využít možností specializovaných knihoven. My se dnes seznámíme především s elegantně navrženou knihovnou core.matrix, protože ta je používána i projektem Incanter.

Poznámka: nesmíme taktéž zapomenout na způsob reprezentace datových struktur v operační paměti. Matice jsou většinou homogenní datovou strukturou, kterou lze v případě, že prvky jsou primitivního datového typu, uložit v kompaktní podobě. U obecných vektorů a sekvencí jazyka Clojure tomu tak však není. Problematikou uložené polí primitivních typů na haldě v JVM jsme se zabývali v článku Pohled pod kapotu JVM – jak efektivně jsou uložena pole a řetězce na haldě? (viz například šestou kapitolu).

V přednášce nazvané velmi příhodně „Enter the Matrix“, která je dostupná na adrese http://www.slideshare.net/mi­keranderson/2013–1114-enter-thematrix, je mj. ukázáno, jakým způsobem jsou v Clojure implementována různá paradigmata programování. Díky podpoře maker a způsobu zápisu programového kódu v Clojure lze velmi snadno implementovat různé doménově specifické jazyky (DSL), mj. i právě jazyk pro array programming:

Paradigma Jazyk Implementace v Clojure
funkcionální Haskell clojure.core
OOP Smalltalk clojure.core
metaprogramování Lisp clojure.core
logické Prolog core.logic
array programming APL, J core.matrix
Poznámka: původní tabulka byla upravena a doplněna.

8. Základní informace o knihovně core.matrix

Knihovna nazvaná core.matrix je určená těm vývojářům, kteří ve svých projektech potřebují provádět velké množství operací s maticemi různých dimenzí, a to na poměrně vysoké úrovni, tj. bez nutnosti přesně specifikovat, jak mají být matice uloženy v paměti, jakým způsobem provádět operaci násobení matic atd. Díky tomuto přístupu a taktéž díky vlastnostem programovacího jazyka Clojure (existence tzv. threading makra a funkcí vyššího řádu) se práce s maticemi do značné míry začíná podobat práci v APL, až na ten rozdíl, že algoritmy zapisované v Clojure jsou pro většinu vývojářů přece jen čitelnější :-). Taktéž je důležité, že rozhraní definované v knihovně core.matrix může mít několik implementací. V současnosti se jedná o vectorz-clj, Clatrix a NDArray. V core.matrix navíc došlo k rozšíření operátorů +, – atd. takovým způsobem, že je lze použít i pro zpracování vektorů a matic (ve skutečnosti se samozřejmě nejedná o skutečné operátory, protože tento koncept Clojure nepotřebuje).

9. Konstruktory matic

Skutečný vektor či matice se vytvoří konstruktorem matrix. Povšimněte si, že tomuto konstruktoru můžete předat klasický vektor programovacího jazyka Clojure; samozřejmě lze předat i vektor vektorů:

incanter.irepl=> (matrix [[1 2] [4 5]])
#vectorz/matrix [[1.0,2.0],
[4.0,5.0]]
 
incanter.irepl=> (matrix [1 2 3])
#vectorz/vector [1.0,2.0,3.0]

Dalším způsobem konstrukce matice je určení hodnoty všech prvků; za touto hodnotou následuje určení rozměrů matice:

incanter.irepl=> (matrix 0 10 10)
#vectorz/matrix [[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],
[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],
[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],
[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],
[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],
[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],
[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],
[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],
[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],
[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0]]

Povšimněte si, že i zlomky se automaticky převádí na typ float:

incanter.irepl=> (matrix 1/2 5 5)
#vectorz/matrix [[0.5,0.5,0.5,0.5,0.5],
[0.5,0.5,0.5,0.5,0.5],
[0.5,0.5,0.5,0.5,0.5],
[0.5,0.5,0.5,0.5,0.5],
[0.5,0.5,0.5,0.5,0.5]]

Nejdříve se zadává počet řádků, poté počet sloupců:

incanter.irepl=> (matrix 1 3 5)
#vectorz/matrix [[1.0,1.0,1.0,1.0,1.0],
[1.0,1.0,1.0,1.0,1.0],
[1.0,1.0,1.0,1.0,1.0]]
incanter.irepl=> (matrix 1 8 3)
#vectorz/matrix [[1.0,1.0,1.0],
[1.0,1.0,1.0],
[1.0,1.0,1.0],
[1.0,1.0,1.0],
[1.0,1.0,1.0],
[1.0,1.0,1.0],
[1.0,1.0,1.0],
[1.0,1.0,1.0]]

10. Vytvoření matice ze sekvence

Vytvoření dvourozměrné matice výčtem prvků již známe:

incanter.irepl=> (matrix [[1 2 3] [4 5 6] [7 8 9]])
#vectorz/matrix [[1.0,2.0,3.0],
[4.0,5.0,6.0],
[7.0,8.0,9.0]]

Alternativně je možné prvky specifikovat v jednorozměrném vektoru a pouze přidat informaci o tom, jaké má matice rozměry:

incanter.irepl=> (matrix [1 2 3 4 5 6 7 8 9] 3)
#vectorz/matrix [[1.0,2.0,3.0],
[4.0,5.0,6.0],
[7.0,8.0,9.0]]

Přebytečné prvky, které netvoří obdélníkovou matici, se nepoužijí:

incanter.irepl=> (matrix [1 2 3 4 5 6 7 8 9] 2)
#vectorz/matrix [[1.0,2.0],
[3.0,4.0],
[5.0,6.0],
[7.0,8.0]]

Kromě vektoru je samozřejmě použít libovolnou sekvenci podporovanou programovacím jazykem Clojure, takže matici 3×3 prvky můžeme vytvořit i takto:

incanter.irepl=> (matrix (range 1 10) 3)
#vectorz/matrix [[1.0,2.0,3.0],
[4.0,5.0,6.0],
[7.0,8.0,9.0]]

Sloupcový vektor se vytvoří stejně snadno:

incanter.irepl=> (matrix (range 1 10) 1)
#vectorz/matrix [[1.0],
[2.0],
[3.0],
[4.0],
[5.0],
[6.0],
[7.0],
[8.0],
[9.0]]

Samozřejmě je možné použít i složitější zápisy – zde se žádná omezení nekladou:

incanter.irepl=> (matrix (map #(* 2 %) (take 25 (range))) 5)
#vectorz/matrix [[0.0,2.0,4.0,6.0,8.0],
[10.0,12.0,14.0,16.0,18.0],
[20.0,22.0,24.0,26.0,28.0],
[30.0,32.0,34.0,36.0,38.0],
[40.0,42.0,44.0,46.0,48.0]]
Poznámka: v předchozím příkladu je použita nekonečná lazy sekvence, kterou zpracováváme a získáme prvních 25 prvků.

11. Matice jako sekvence řádků

Z pohledu jazyka Clojure lze matici zpracovávat jako sekvenci jednotlivých řádků, což je poměrně užitečná vlastnost. Nejprve si vytvořme matici o rozměrech 3×3 prvky:

incanter.irepl=> (def M (matrix (range 1 10) 3))
#'incanter.irepl/M

Kontrola obsahu matice:

incanter.irepl=> M
#vectorz/matrix [[1.0,2.0,3.0],
[4.0,5.0,6.0],
[7.0,8.0,9.0]]

Dále můžeme získat první řádek matice, a to běžnou funkcí first:

incanter.irepl=> (first M)
#vectorz/vector [1.0,2.0,3.0]
Poznámka: v tomto případě se vrátil vektor.

Získání všech řádků kromě řádku prvního:

incanter.irepl=> (rest M)
(#vectorz/vector [4.0,5.0,6.0] #vectorz/vector [7.0,8.0,9.0])
Poznámka: nyní se vrátila sekvence vektorů, přesně podle popisu funkce rest.

Díky tomu, že v základní knihovně jazyka Clojure nalezneme velké množství funkcí a maker pro zpracování sekvencí, lze například snadno sečíst všechny hodnoty v jednotlivých sloupcích matice:

incanter.irepl=> (reduce plus M)
#vectorz/vector [12.0,15.0,18.0]

Popř. si naopak můžeme vyčíslit součty prvků na jednotlivých řádcích:

incanter.irepl=> (map sum M)
(6.0 15.0 24.0)

Poznámka: povšimněte si, že se pokaždé vrátil jiný datový typ. Z tohoto důvodu je lepší při práci s maticemi používat operace popsané níže.

Další operace (pravděpodobně ne příliš užitečné):

incanter.irepl=> (map first M)
(1.0 4.0 7.0)
 
incanter.irepl=> (map second M)
(2.0 5.0 8.0)

12. Základní operace s maticemi

Podívejme se nyní na některé základní operace s maticemi. Tomuto tématu bude věnován samostatný článek, ale krátkou ukázku si můžeme předvést již dnes. Nejdříve si opět vytvoříme matici:

incanter.irepl=> (def A (matrix [[1 2 3]
            #_=>                 [4 5 6]
            #_=>                 [7 8 9]]))
#'incanter.irepl/A

Broadcasting umožňuje převést číslo na matici stejného řádu, jakou má druhý operand:

incanter.irepl=> ($= A + 2)
#vectorz/matrix [[3.0,4.0,5.0],
[6.0,7.0,8.0],
[9.0,10.0,11.0]]

Vynásobení matice konstantou (skalárem):

incanter.irepl=> ($= A * -1)
#vectorz/matrix [[-1.0,-2.0,-3.0],
[-4.0,-5.0,-6.0],
[-7.0,-8.0,-9.0]]

Vynásobení matice a vektoru, který byl opět rozšířen na matici:

incanter.irepl=> ($= A * [5 0 5])
#vectorz/matrix [[5.0,0.0,15.0],
[20.0,0.0,30.0],
[35.0,0.0,45.0]]

Skutečný „maticový“ součin matice a vektoru:

incanter.irepl=> (mmult A [5 0 0])
#vectorz/vector [5.0,20.0,35.0]

Matici můžeme transponovat:

incanter.irepl=> (trans A)
#vectorz/matrix [[1.0,4.0,7.0],
[2.0,5.0,8.0],
[3.0,6.0,9.0]]

Můžeme provést vynásobení původní matice s maticí transponovanou:

incanter.irepl=> (mmult A (trans A))
#vectorz/matrix [[14.0,32.0,50.0],
[32.0,77.0,122.0],
[50.0,122.0,194.0]]

Další složitější varianta:

incanter.irepl=> (mmult A (trans A) A)
#vectorz/matrix [[492.0,588.0,684.0],
[1194.0,1425.0,1656.0],
[1896.0,2262.0,2628.0]]

13. Výpočet inverzní matice

Výpočet inverzní matice zajišťuje funkce solve:

incanter.irepl=> (solve (matrix [[2 0 0] [0 2 0] [0 0 2]]))
#vectorz/matrix [[0.5,0.0,0.0],
[0.0,0.5,0.0],
[0.0,0.0,0.5]]

Kontrola předchozího výpočtu:

incanter.irepl=> (mmult (solve (matrix [[2 0 0] [0 2 0] [0 0 2]])) (matrix [[2 0 0] [0 2 0] [0 0 2]]))
#vectorz/matrix [[1.0,0.0,0.0],
[0.0,1.0,0.0],
[0.0,0.0,1.0]]
Poznámka: pokud inverzní matici nelze vypočítat, vrátí se nil.

14. Symbolické výpočty

Knihovna Incanter sice v žádném případě nedokáže nahradit Mathematicu nebo Maple, ovšem obsahuje i modul pro symbolické výpočty, tj. (velmi zjednodušeně řečeno) pro úpravy výrazů a rovnic na základě manipulace se symboli a nikoli na základě numerických výpočtů. Prozatím je podporován především výpočet derivace podle zvolené proměnné. Ukažme si jednoduché příklady.

Načtení knihovny:

incanter.irepl=> (use '(incanter symbolic))
nil

Derivace funkce sinus podle proměnné x:

incanter.irepl=> (deriv (sin x) x)
(cos x)

Složitější výraz s jedinou proměnnou:

incanter.irepl=> (deriv (cos (* x x)) x)
(* (+ x x) (* -1 (sin (* x x))))

Další nepatrně složitější výraz:

incanter.irepl=> (deriv (+ (cos x) (tan x)) x)
(+ (pow (cos x) -2) (* -1 (sin x)))

Derivace stejné funkce, ovšem pro rozdílné proměnné:

incanter.irepl=> (deriv (/ (+ (cos x) (tan y)) (ln z)) x)
(+ (* (* (pow (* 1 (+ (cos x) (tan y)) (ln z))) -1) (* -1 (sin x))) (* (* -1 (deriv* (pow (* 1 (+ (cos x) (tan y)) (ln z))) x)) (+ (cos x) (tan y))))
 
incanter.irepl=> (deriv (/ (+ (cos x) (tan y)) (ln z)) y)
(+ (* (* (pow (* 1 (+ (cos x) (tan y)) (ln z))) -1) (pow (cos y) -2)) (* (* -1 (deriv* (pow (* 1 (+ (cos x) (tan y)) (ln z))) y)) (+ (cos x) (tan y))))
 
incanter.irepl=> (deriv (/ (+ (cos x) (tan y)) (ln z)) z)
(* (* -1 (deriv* (pow (* 1 (+ (cos x) (tan y)) (ln z))) z)) (+ (cos x) (tan y)))

15. Jednoduché grafy s průběhy funkcí

Nejjednodušším typem grafu je graf s průběhem zvolené funkce. Samotný graf se vytvoří pomocí function-plot, což je funkce vyššího řádu, které lze předat libovolnou jinou aritmetickou funkci a taktéž rozsah hodnot nezávislé proměnné. Výsledek lze zobrazit funkcí view. Nesmíte samozřejmě zapomenout na import knihovny charts:

(use '(incanter core charts))
 
(view (function-plot (fn [x] (sin x)) -10 10))

Obrázek 8: Graf s průběhem funkce sinus.

Osobně ovšem doporučuji jiný styl zápisu využívající threading makro:

(->
    (fn [x] (sin x))
    (function-plot -10 10)
    view)

Výsledkem bude naprosto stejný graf, jako v příkladu předchozím.

16. Zápis vzorců způsobem převzatým z LaTeXu

Jen v rychlosti (alespoň prozatím) si ukažme, jakým způsobem se do grafů přidávají vzorce zapsané a vysázené podobně, jako v LaTeXu. Používá se k tomu funkce add-latex, například:

(add-latex 0 250 "x^3 - 5x^2 + 3x +5")

Tato funkce přidá návěští přímo do grafu. Nesmíme samozřejmě zapomenout na importy:

(use '(incanter core charts latex))

Můžeme zde s výhodou použít standardní makro doto:

(doto (function-plot (fn [x] ($= x ** 3 - 5 * x ** 2 + 3 * x + 5)) -10 10)
  (add-latex 0 250 "x^3 - 5x^2 + 3x +5")
  view)

Obrázek 9: Výsledek předchozího příkazu.

17. Uložení grafů do rastrových obrázků i do vektorového výkresu

Kromě funkce view, která graf vykreslí do samostatného okna, ho můžeme uložit do rastrového souboru funkcí save. Například:

(ns png-output
  (:use (incanter core stats charts svg)))
 
(save (histogram (sample-normal 1000))  "histogram1.png")
(save (histogram (sample-normal 100000) :nbins 50 :title "Normální rozložení" :legend true :y-label "Četnost")  "histogram2.png")
(save (function-plot (fn [x] ($= x ** 3 - 5 * x ** 2 + 3 * x + 5)) -10 10)  "funkce.png")

Někdy může být výhodnější použít export do vektorového formátu SVG:

(ns svg-output
  (:use (incanter core stats charts svg)))
 
(save-svg (histogram (sample-normal 1000))  "histogram1.svg")
(save-svg (histogram (sample-normal 100000) :nbins 50 :title "Normální rozložení" :legend true :y-label "Četnost")  "histogram2.svg")
(save-svg (function-plot (fn [x] ($= x ** 3 - 5 * x ** 2 + 3 * x + 5)) -10 10)  "funkce.svg")

Podrobnosti si vysvětlíme příště.

18. Repositář s demonstračními příklady

Zdrojové kódy všech dnes popsaných demonstračních příkladů byly uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/incanter-examples (stále na GitHubu :-). V případě, že nebudete chtít klonovat celý repositář (ten je ovšem stále velmi malý, dnes má doslova několik kilobajtů), můžete namísto toho použít odkazy na jednotlivé příklady, které naleznete v následující tabulce:

19. Předchozí články o programovacím jazyku Clojure a jeho knihovnách

  1. Clojure 1: Úvod
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm/
  2. Clojure 2: Symboly, kolekce atd.
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-2-cast/
  3. Clojure 3: Funkcionální programování
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-3-cast-funkcionalni-programovani/
  4. Clojure 4: Kolekce, sekvence a lazy sekvence
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-4-cast-kolekce-sekvence-a-lazy-sekvence/
  5. Clojure 5: Sekvence, lazy sekvence a paralelní programy
    http://www.root.cz/clanky/clojure-a-bezpecne-aplikace-pro-jvm-sekvence-lazy-sekvence-a-paralelni-programy/
  6. Clojure 6: Podpora pro paralelní programování
    http://www.root.cz/clanky/programovaci-jazyk-clojure-6-futures-nejsou-jen-financni-derivaty/
  7. Clojure 7: Další funkce pro paralelní programování
    http://www.root.cz/clanky/programovaci-jazyk-clojure-7-dalsi-podpurne-prostredky-pro-paralelni-programovani/
  8. Clojure 8: Identity, stavy, neměnné hodnoty a reference
    http://www.root.cz/clanky/programovaci-jazyk-clojure-8-identity-stavy-nemenne-hodnoty-a-referencni-typy/
  9. Clojure 9: Validátory, pozorovatelé a kooperace s Javou
    http://www.root.cz/clanky/programovaci-jazyk-clojure-9-validatory-pozorovatele-a-kooperace-mezi-clojure-a-javou/
  10. Clojure 10: Kooperace mezi Clojure a Javou
    http://www.root.cz/clanky/programovaci-jazyk-clojure-10-kooperace-mezi-clojure-a-javou-pokracovani/
  11. Clojure 11: Generátorová notace seznamu/list comprehension
    http://www.root.cz/clanky/programovaci-jazyk-clojure-11-generatorova-notace-seznamu-list-comprehension/
  12. Clojure 12: Překlad programů z Clojure do bajtkódu JVM I:
    http://www.root.cz/clanky/programovaci-jazyk-clojure-12-preklad-programu-z-clojure-do-bajtkodu-jvm/
  13. Clojure 13: Překlad programů z Clojure do bajtkódu JVM II:
    http://www.root.cz/clanky/programovaci-jazyk-clojure-13-preklad-programu-z-clojure-do-bajtkodu-jvm-pokracovani/
  14. Clojure 14: Základy práce se systémem maker
    http://www.root.cz/clanky/programovaci-jazyk-clojure-14-zaklady-prace-se-systemem-maker/
  15. Clojure 15: Tvorba uživatelských maker
    http://www.root.cz/clanky/programovaci-jazyk-clojure-15-tvorba-uzivatelskych-maker/
  16. Clojure 16: Složitější uživatelská makra
    http://www.root.cz/clanky/programovaci-jazyk-clojure-16-slozitejsi-uzivatelska-makra/
  17. Clojure 17: Využití standardních maker v praxi
    http://www.root.cz/clanky/programovaci-jazyk-clojure-17-vyuziti-standardnich-maker-v-praxi/
  18. Clojure 18: Základní techniky optimalizace aplikací
    http://www.root.cz/clanky/programovaci-jazyk-clojure-18-zakladni-techniky-optimalizace-aplikaci/
  19. Clojure 19: Vývojová prostředí pro Clojure
    http://www.root.cz/clanky/programovaci-jazyk-clojure-19-vyvojova-prostredi-pro-clojure/
  20. Clojure 20: Vývojová prostředí pro Clojure (Vimu s REPL)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-20-vyvojova-prostredi-pro-clojure-integrace-vimu-s-repl/
  21. Clojure 21: ClojureScript aneb překlad Clojure do JS
    http://www.root.cz/clanky/programovaci-jazyk-clojure-21-clojurescript-aneb-preklad-clojure-do-javascriptu/
  22. Leiningen: nástroj pro správu projektů napsaných v Clojure
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure/
  23. Leiningen: nástroj pro správu projektů napsaných v Clojure (2)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-2/
  24. Leiningen: nástroj pro správu projektů napsaných v Clojure (3)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-3/
  25. Leiningen: nástroj pro správu projektů napsaných v Clojure (4)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-4/
  26. Leiningen: nástroj pro správu projektů napsaných v Clojure (5)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-5/
  27. Leiningen: nástroj pro správu projektů napsaných v Clojure (6)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-6/
  28. Programovací jazyk Clojure a databáze (1.část)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-databaze-1-cast/
  29. Pluginy pro Leiningen
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-pluginy-pro-leiningen/
  30. Programovací jazyk Clojure a knihovny pro práci s vektory a maticemi
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-knihovny-pro-praci-s-vektory-a-maticemi/
  31. Programovací jazyk Clojure a knihovny pro práci s vektory a maticemi (2)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-knihovny-pro-praci-s-vektory-a-maticemi-2/
  32. Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk
    http://www.root.cz/clanky/programovaci-jazyk-clojure-synteza-proceduralnich-textur-s-vyuzitim-knihovny-clisk/
  33. Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk (2)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-synteza-proceduralnich-textur-s-vyuzitim-knihovny-clisk-2/
  34. Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure
    http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure/
  35. Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure (2)
    http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure-2/
  36. Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure (3)
    http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure-3/
  37. Programovací jazyk Clojure a práce s Gitem
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-prace-s-gitem/
  38. Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk (dokončení)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-synteza-proceduralnich-textur-s-vyuzitim-knihovny-clisk-dokonceni/
  39. Pixie: lehký skriptovací jazyk s „kouzelnými“ schopnostmi
    https://www.root.cz/clanky/pixie-lehky-skriptovaci-jazyk-s-kouzelnymi-schopnostmi/
  40. Programovací jazyk Pixie: funkce ze základní knihovny a použití FFI
    https://www.root.cz/clanky/pro­gramovaci-jazyk-pixie-funkce-ze-zakladni-knihovny-a-pouziti-ffi/
  41. Novinky v Clojure verze 1.9.0
    https://www.root.cz/clanky/novinky-v-clojure-verze-1–9–0/
  42. Validace dat s využitím knihovny spec v Clojure 1.9.0
    https://www.root.cz/clanky/validace-dat-s-vyuzitim-knihovny-spec-v-clojure-1–9–0/
  43. Použití jazyka Gherkin při tvorbě testovacích scénářů pro aplikace psané v Clojure
    https://www.root.cz/clanky/pouziti-jazyka-gherkin-pri-tvorbe-testovacich-scenaru-pro-aplikace-psane-v-nbsp-clojure/
  44. Použití jazyka Gherkin při tvorbě testovacích scénářů pro aplikace psané v Clojure (2)
    https://www.root.cz/clanky/pouziti-jazyka-gherkin-pri-tvorbe-testovacich-scenaru-pro-aplikace-psane-v-nbsp-clojure-2/

20. Odkazy na Internetu

  1. Incanter is a Clojure-based, R-like platform for statistical computing and graphics.
    http://incanter.org/
  2. Evolution of incanter (Gource Visualization)
    https://www.youtube.com/wat­ch?v=TVfL5nPELr4
  3. Questions tagged [incanter] (na Stack Overflow)
    https://stackoverflow.com/qu­estions/tagged/incanter?sor­t=active
  4. Data Sorcery with Clojure
    https://data-sorcery.org/contents/
  5. Back to the Future: Lisp as a Base for a Statistical Computing System
    https://rd.springer.com/chap­ter/10.1007/978–3–7908–2084–3_2
  6. Incanter Cheat Sheet
    http://incanter.org/docs/incanter-cheat-sheet.pdf
  7. Back to the Future: Lisp as a Base for a Statistical Computing System (celá verze článku)
    https://www.researchgate.net/pu­blication/227019917_Back_to_the_Fu­ture_Lisp_as_a_Base_for_a_Sta­tistical_Computing_System
  8. Lisp-Stat Information
    http://homepage.cs.uiowa.e­du/~luke/xls/xlsinfo/
  9. Sample Plots in Incanter
    https://github.com/incanter/in­canter/wiki/Sample-Plots-in-Incanter#line
  10. vectorz-clj
    https://github.com/mikera/vectorz-clj
  11. vectorz – Examples
    https://github.com/mikera/vectorz-clj/wiki/Examples
  12. Array Programming
    https://en.wikipedia.org/wi­ki/Array_programming
  13. Discovering Array Languages
    http://archive.vector.org­.uk/art10008110
  14. no stinking loops – Kalothi
    http://www.nsl.com/
  15. Vector (obsahuje odkazy na články, knihy a blogy o programovacích jazycích APL, J a K)
    http://www.vector.org.uk/
  16. Colt
    http://dst.lbl.gov/ACSSoftware/colt/
  17. Parallel Colt: Open Source Libraries for High Performance Scientific and Technical Computing in Java
    http://incanter.org/docs/pa­rallelcolt/api/
  18. Processing
    https://www.processing.org/
  19. The R Project for Statistical Computing
    https://www.r-project.org/
  20. Humane test output for clojure.test
    https://github.com/pjstadig/humane-test-output
  21. iota
    https://github.com/juxt/iota
  22. 5 Differences between clojure.spec and Schema
    https://lispcast.com/clojure.spec-vs-schema/
  23. Schema: Clojure(Script) library for declarative data description and validation
    https://github.com/plumatic/schema
  24. Zip archiv s Clojure 1.9.0
    http://repo1.maven.org/ma­ven2/org/clojure/clojure/1­.9.0/clojure-1.9.0.zip
  25. Clojure 1.9 is now available
    https://clojure.org/news/2017/12/08/clo­jure19
  26. Deps and CLI Guide
    https://clojure.org/guides/dep­s_and_cli
  27. Changes to Clojure in Version 1.9
    https://github.com/clojure/clo­jure/blob/master/changes.md
  28. clojure.spec – Rationale and Overview
    https://clojure.org/about/spec
  29. Zip archiv s Clojure 1.8.0
    http://repo1.maven.org/ma­ven2/org/clojure/clojure/1­.8.0/clojure-1.8.0.zip
  30. Clojure 1.8 is now available
    http://clojure.org/news/2016/01/19/clo­jure18
  31. Socket Server REPL
    http://dev.clojure.org/dis­play/design/Socket+Server+REPL
  32. CLJ-1671: Clojure socket server
    http://dev.clojure.org/jira/browse/CLJ-1671
  33. CLJ-1449: Add clojure.string functions for portability to ClojureScript
    http://dev.clojure.org/jira/browse/CLJ-1449
  34. Launching a Socket Server
    http://clojure.org/referen­ce/repl_and_main#_launchin­g_a_socket_server
  35. API for clojure.string
    http://clojure.github.io/clo­jure/branch-master/clojure.string-api.html
  36. Clojars:
    https://clojars.org/
  37. Seznam knihoven na Clojars:
    https://clojars.org/projects
  38. Clojure Cookbook: Templating HTML with Enlive
    https://github.com/clojure-cookbook/clojure-cookbook/blob/master/07_webapps/7–11_enlive.asciidoc
  39. An Introduction to Enlive
    https://github.com/swannodette/enlive-tutorial/
  40. Enlive na GitHubu
    https://github.com/cgrand/enlive
  41. Expectations: příklady atd.
    http://jayfields.com/expectations/
  42. Expectations na GitHubu
    https://github.com/jaycfi­elds/expectations
  43. Lein-expectations na GitHubu
    https://github.com/gar3thjon3s/lein-expectations
  44. Testing Clojure With Expectations
    https://semaphoreci.com/blog/2014/09/23/tes­ting-clojure-with-expectations.html
  45. Clojure testing TDD/BDD libraries: clojure.test vs Midje vs Expectations vs Speclj
    https://www.reddit.com/r/Clo­jure/comments/1viilt/cloju­re_testing_tddbdd_librari­es_clojuretest_vs/
  46. Testing: One assertion per test
    http://blog.jayfields.com/2007/06/tes­ting-one-assertion-per-test.html
  47. Rewriting Your Test Suite in Clojure in 24 hours
    http://blog.circleci.com/rewriting-your-test-suite-in-clojure-in-24-hours/
  48. Clojure doc: zipper
    http://clojuredocs.org/clo­jure.zip/zipper
  49. Clojure doc: parse
    http://clojuredocs.org/clo­jure.xml/parse
  50. Clojure doc: xml-zip
    http://clojuredocs.org/clojure.zip/xml-zip
  51. Clojure doc: xml-seq
    http://clojuredocs.org/clo­jure.core/xml-seq
  52. Parsing XML in Clojure
    https://github.com/clojuredocs/guides
  53. Clojure Zipper Over Nested Vector
    https://vitalyper.wordpres­s.com/2010/11/23/clojure-zipper-over-nested-vector/
  54. Understanding Clojure's PersistentVector implementation
    http://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation
  55. Understanding Clojure's PersistentHashMap (deftwice…)
    http://blog.higher-order.net/2009/09/08/understanding-clojures-persistenthashmap-deftwice.html
  56. Assoc and Clojure's PersistentHashMap: part ii
    http://blog.higher-order.net/2010/08/16/assoc-and-clojures-persistenthashmap-part-ii.html
  57. Ideal Hashtrees (paper)
    http://lampwww.epfl.ch/pa­pers/idealhashtrees.pdf
  58. Clojure home page
    http://clojure.org/
  59. Clojure (downloads)
    http://clojure.org/downloads
  60. Clojure Sequences
    http://clojure.org/sequences
  61. Clojure Data Structures
    http://clojure.org/data_structures
  62. The Structure and Interpretation of Computer Programs: 2.2.1 Representing Sequences
    http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec2.2.1
  63. The Structure and Interpretation of Computer Programs: 3.3.1 Mutable List Structure
    http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-22.html#%_sec3.3.1
  64. Clojure – Functional Programming for the JVM
    http://java.ociweb.com/mar­k/clojure/article.html
  65. Clojure quick reference
    http://faustus.webatu.com/clj-quick-ref.html
  66. 4Clojure
    http://www.4clojure.com/
  67. ClojureDoc (rozcestník s dokumentací jazyka Clojure)
    http://clojuredocs.org/
  68. Clojure (na Wikipedia EN)
    http://en.wikipedia.org/wiki/Clojure
  69. Clojure (na Wikipedia CS)
    http://cs.wikipedia.org/wiki/Clojure
  70. SICP (The Structure and Interpretation of Computer Programs)
    http://mitpress.mit.edu/sicp/
  71. Pure function
    http://en.wikipedia.org/wi­ki/Pure_function
  72. Funkcionální programování
    http://cs.wikipedia.org/wi­ki/Funkcionální_programová­ní
  73. Čistě funkcionální (datové struktury, jazyky, programování)
    http://cs.wikipedia.org/wi­ki/Čistě_funkcionální
  74. Clojure Macro Tutorial (Part I, Getting the Compiler to Write Your Code For You)
    http://www.learningclojure­.com/2010/09/clojure-macro-tutorial-part-i-getting.html
  75. Clojure Macro Tutorial (Part II: The Compiler Strikes Back)
    http://www.learningclojure­.com/2010/09/clojure-macro-tutorial-part-ii-compiler.html
  76. Clojure Macro Tutorial (Part III: Syntax Quote)
    http://www.learningclojure­.com/2010/09/clojure-macro-tutorial-part-ii-syntax.html
  77. Tech behind Tech: Clojure Macros Simplified
    http://techbehindtech.com/2010/09/28/clo­jure-macros-simplified/
  78. Fatvat – Exploring functional programming: Clojure Macros
    http://www.fatvat.co.uk/2009/02/clo­jure-macros.html
  79. Eulerovo číslo
    http://cs.wikipedia.org/wi­ki/Eulerovo_číslo
  80. List comprehension
    http://en.wikipedia.org/wi­ki/List_comprehension
  81. List Comprehensions in Clojure
    http://asymmetrical-view.com/2008/11/18/list-comprehensions-in-clojure.html
  82. Clojure Programming Concepts: List Comprehension
    http://en.wikibooks.org/wi­ki/Clojure_Programming/Con­cepts#List_Comprehension
  83. Clojure core API: for macro
    http://clojure.github.com/clo­jure/clojure.core-api.html#clojure.core/for
  84. cirrus machina – The Clojure for macro
    http://www.cirrusmachina.com/blog/com­ment/the-clojure-for-macro/
  85. Riastradh's Lisp Style Rules
    http://mumble.net/~campbe­ll/scheme/style.txt
  86. Dynamic Languages Strike Back
    http://steve-yegge.blogspot.cz/2008/05/dynamic-languages-strike-back.html
  87. Scripting: Higher Level Programming for the 21st Century
    http://www.tcl.tk/doc/scripting.html
  88. Java Virtual Machine Support for Non-Java Languages
    http://docs.oracle.com/ja­vase/7/docs/technotes/gui­des/vm/multiple-language-support.html
  89. Třída java.lang.String
    http://docs.oracle.com/ja­vase/7/docs/api/java/lang/Strin­g.html
  90. Třída java.lang.StringBuffer
    http://docs.oracle.com/ja­vase/7/docs/api/java/lang/Strin­gBuffer.html
  91. Třída java.lang.StringBuilder
    http://docs.oracle.com/ja­vase/7/docs/api/java/lang/Strin­gBuilder.html
  92. StringBuffer versus String
    http://www.javaworld.com/ar­ticle/2076072/build-ci-sdlc/stringbuffer-versus-string.html
  93. Threading macro (dokumentace k jazyku Clojure)
    https://clojure.github.io/clo­jure/clojure.core-api.html#clojure.core/->
  94. Understanding the Clojure → macro
    http://blog.fogus.me/2009/09/04/un­derstanding-the-clojure-macro/
  95. clojure.inspector
    http://clojure.github.io/clo­jure/clojure.inspector-api.html
  96. The Clojure Toolbox
    http://www.clojure-toolbox.com/
  97. Unit Testing in Clojure
    http://nakkaya.com/2009/11/18/unit-testing-in-clojure/
  98. Testing in Clojure (Part-1: Unit testing)
    http://blog.knoldus.com/2014/03/22/tes­ting-in-clojure-part-1-unit-testing/
  99. API for clojure.test – Clojure v1.6 (stable)
    https://clojure.github.io/clo­jure/clojure.test-api.html
  100. Leiningen: úvodní stránka
    http://leiningen.org/
  101. Leiningen: Git repository
    https://github.com/techno­mancy/leiningen
  102. leiningen-win-installer
    http://leiningen-win-installer.djpowell.net/
  103. Clojure.org: Vars and the Global Environment
    http://clojure.org/Vars
  104. Clojure.org: Refs and Transactions
    http://clojure.org/Refs
  105. Clojure.org: Atoms
    http://clojure.org/Atoms
  106. Clojure.org: Agents as Asynchronous Actions
    http://clojure.org/agents
  107. Transient Data Structureshttp://clojure.or­g/transients
  108. Programovací jazyk Clojure a práce s Gitem (2)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-prace-s-gitem-2/
  109. Programovací jazyk Clojure – triky při práci s řetězci
    http://www.root.cz/clanky/programovaci-jazyk-clojure-triky-pri-praci-s-retezci/
  110. Programovací jazyk Clojure – triky při práci s kolekcemi
    http://www.root.cz/clanky/programovaci-jazyk-clojure-triky-pri-praci-s-kolekcemi/
  111. Programovací jazyk Clojure – práce s mapami a množinami
    http://www.root.cz/clanky/programovaci-jazyk-clojure-prace-s-mapami-a-mnozinami/
  112. Programovací jazyk Clojure – základy zpracování XML
    http://www.root.cz/clanky/programovaci-jazyk-clojure-zaklady-zpracovani-xml/
  113. Programovací jazyk Clojure – testování s využitím knihovny Expectations
    http://www.root.cz/clanky/programovaci-jazyk-clojure-testovani-s-vyuzitim-knihovny-expectations/
  114. Programovací jazyk Clojure – některé užitečné triky použitelné (nejenom) v testech
    http://www.root.cz/clanky/programovaci-jazyk-clojure-nektere-uzitecne-triky-pouzitelne-nejenom-v-testech/
  115. Enlive – výkonný šablonovací systém pro jazyk Clojure
    http://www.root.cz/clanky/enlive-vykonny-sablonovaci-system-pro-jazyk-clojure/
  116. Nástroj Leiningen a programovací jazyk Clojure: tvorba vlastních knihoven pro veřejný repositář Clojars
    http://www.root.cz/clanky/nastroj-leiningen-a-programovaci-jazyk-clojure-tvorba-vlastnich-knihoven-pro-verejny-repositar-clojars/
  117. Novinky v Clojure verze 1.8.0
    http://www.root.cz/clanky/novinky-v-clojure-verze-1–8–0/
  118. Asynchronní programování v Clojure s využitím knihovny core.async
    http://www.root.cz/clanky/asynchronni-programovani-v-clojure-s-vyuzitim-knihovny-core-async/
  119. Asynchronní programování v Clojure s využitím knihovny core.async (pokračování)
    http://www.root.cz/clanky/asynchronni-programovani-v-clojure-s-vyuzitim-knihovny-core-async-pokracovani/
  120. Asynchronní programování v Clojure s využitím knihovny core.async (dokončení)
    http://www.root.cz/clanky/asynchronni-programovani-v-clojure-s-vyuzitim-knihovny-core-async-dokonceni/
  121. Vytváříme IRC bota v programovacím jazyce Clojure
    http://www.root.cz/clanky/vytvarime-irc-bota-v-programovacim-jazyce-clojure/
  122. Gorilla REPL: interaktivní prostředí pro programovací jazyk Clojure
    https://www.root.cz/clanky/gorilla-repl-interaktivni-prostredi-pro-programovaci-jazyk-clojure/
  123. Multimetody v Clojure aneb polymorfismus bez použití OOP
    https://www.root.cz/clanky/multimetody-v-clojure-aneb-polymorfismus-bez-pouziti-oop/
  124. Práce s externími Java archivy v programovacím jazyku Clojure
    https://www.root.cz/clanky/prace-s-externimi-java-archivy-v-programovacim-jazyku-clojure/
Našli jste v článku chybu?