Hlavní navigace

Tvorba jednoduchých grafů v systému Incanter

Pavel Tišnovský

Ve třetím článku o systému Incanter se seznámíme s tvorbou grafů, které mnohdy tvoří významný (někdy i jediný) výsledek statistických výpočtů. Incanter pro tvorbu grafů interně používá knihovnu JFreeChart.

Doba čtení: 26 minut

11. Vliv hodnoty dx na numerický výpočet derivace

12. Přidání popisků do grafu

13. Parametrický graf

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

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

16. Odkazy na Internetu

1. Tvorba jednoduchých grafů v systému Incanter

V systému Incanter je samozřejmě možné vykreslovat různé typy grafů. Podobně, jako je tomu například v Matplotlibu nebo v systému R, existuje i v Incanteru možnost tvořit sloupcové grafy, spojnicové grafy, koláčové grafy, parametrické grafy atd. Incanter přitom interně využívá knihovnu JFreeChart. V praxi je tedy možné (a někdy i nutné) modifikovat vykreslované grafy přímo manipulací s objekty JFreeChartu – a to díky podpoře tzv. Java interop v programovacím jazyku Clojure. V dnešním článku si popíšeme tvorbu těch nejjednodušších (ale pravděpodobně nejčastěji používaných) grafů – sloupcového grafu, liniového grafu, grafu s průběhem funkce či funkcí a konečně grafu parametrického.

Na začátku si připomeňme, že grafy je možné zobrazit funkcí view. Ovšem kromě této funkce, která graf vykreslí do samostatného okna, ho můžeme uložit do rastrového souboru funkcí save. Alternativně lze použít funkci pojmenovanou save-svg, která graf vyexportuje do vektorového formátu SVG (což je mnohdy výhodnější, jak z hlediska velikosti souboru, tak i možnosti jeho tisku a dalšího zpracování beze ztráty kvality).

2. Sloupcový graf

Jedním z nejjednodušších typů grafů podporovaných systémem Incanter je sloupcový graf, který může být podle konkrétních požadavků orientován jak horizontálně, tak i vertikálně. Tento typ grafu se vytváří zavoláním makra pojmenovaného bar-chart, kterému je nutné předat minimálně dvě informace – sekvenci s popiskami hodnot na x-ové ose a sekvenci se samotnými hodnotami, které se mají do grafu vynést. Obě sekvence by přitom měly mít shodnou délku, což je systémem Incanter kontrolováno při konstrukci grafu. Podívejme se nyní na jednoduchý příklad. Spustíme interaktivní smyčku REPL, přepneme se do nového jmenného prostoru a nejprve provedeme všechny potřebné importy:

(ns simple-plot
  (:use (incanter core stats charts)))

Následně již můžeme nějakým způsobem vypočítat či načíst hodnoty, které se mají do grafu vynést. Pro jednoduchost se bude jednat o výsledky hodů kostkou, konkrétně o deset celočíselných hodnot od 1 do 6:

(def hody-kostkou (take 10 (repeatedly #(inc (rand-int 6)))))

Samotný sloupcový graf se následně vytvoří makrem bar-chart a vykreslí funkcí view, s níž jsme se již seznámili v úvodním článku o projektu Incanter. Prvním parametrem do makra bar-chart předáváme sekvenci hodnot 1..10, která se vypíše na x-ovou osu, druhým parametrem jsou vynášené hodnoty:

(view (bar-chart (range 1 (inc (count hody-kostkou))) hody-kostkou))

Obrázek 1: Sloupcový graf s výchozími popisy os.

Při pohledu na předchozí screenshot jste si pravděpodobně všimli, že popisky os jsou automaticky získány z parametrů předaných makru bar-chart (ostatně právě proto se jedná o makro, aby nedošlo k vyhodnocení parametrů). Můžeme se ostatně jednoduše přesvědčit, co se stane ve chvíli, kdy změníme první parametr (který se ovšem vyhodnotí na tu samou sekvenci 1..10, jako tomu bylo v předchozím příkladu):

(view (bar-chart (range 1 11) hody-kostkou))

Obrázek 2: Kvůli způsobu vyhodnocování maker se automaticky mění i popisy os.

Ve skutečnosti se ovšem prakticky nikdy nespokojíme s výchozím automaticky generovaným popisem os a budeme muset vytvořit popisky vlastní. To se provede jednoduše – předáním nepovinných parametrů se jmény :x-label a y:label makru bar-chart:

(view (bar-chart (range 1 (inc (count hody-kostkou))) hody-kostkou :x-label "Pokusy" :y-label "Výsledek hodu"))

Obrázek 3: Změna popisu os ve sloupcovém grafu.

Poznámka: připomeňme si, že dvojtečkou se v programovacím jazyku Clojure označují takzvané keywords, což jsou neměnné a unikátní hodnoty, které se typicky používají namísto konstantních řetězců (ty jsou sice taky neměnné, ale nikoli unikátní – nejedná se o jedináčky).

3. Přidání legendy a nadpisu do sloupcového grafu

Sloupcový graf je možné, ostatně podobně jako všechny další typy grafů, různým způsobem upravovat, i když je nutno poznamenat, že například Matplotlib nabízí jednodušší možnosti modifikací. Kromě popisků os je možné povolit a nakonfigurovat i zobrazení legendy, která se ve výchozím nastavení umisťuje pod vlastním grafem. Zobrazení legendy se povoluje nepovinným parametrem se jménem :legend:

(view (bar-chart (range 1 (inc (count hody-kostkou))) hody-kostkou :x-label "Pokusy" :y-label "Výsledek hodu" :legend true))

Obrázek 4: Legenda, která byla vytvořena automaticky.

Text legendy se opět automaticky získává z parametrů předaných makru bar-chart, takže je možné provést jednoduchou úpravu a získat odlišnou legendu:

(def indexy (range 1 (inc (count hody-kostkou))))
(view (bar-chart indexy hody-kostkou :x-label "Pokusy" :y-label "Výsledek hodu" :legend true))

Obrázek 5: Explicitně zapsaná legenda.

Poslední jednoduchou úpravou je přidání titulku do grafu. K tomuto účelu se opět používá nepovinný keyword parametr, který se tentokrát jmenuje :title:

(def indexy (range 1 (inc (count hody-kostkou))))
(view (bar-chart indexy hody-kostkou :x-label "Pokusy" :y-label "Výsledek hodu" :legend true :title "Hody kostkou"))

Obrázek 6: Přidání nadpisu do grafu.

4. Sloupcový graf s více kategoriemi

Sloupcové grafy popsané v předchozích dvou kapitolách byly ve skutečnosti velmi jednoduché, protože sloužily pro zobrazení hodnot z jediné kategorie (v našem případě se jednalo o výsledky hodu kostkou). V praxi se ovšem velmi často setkáme s požadavkem, aby se do sloupcového grafu vykreslily hodnoty z několika kategorií. Pěkným příkladem z praxe může být například tento graf s výsledky benchmarků. Pokud budete chtít vytvořit podobný typ grafu, je nutné makru bar-chart předat i parametr pojmenovaný :group-by s definicí jednotlivých kategorií. Opět se podívejme na demonstrační příklad, který tentokrát vznikl úpravou příkladu převzatého přímo z dokumentace k projektu Incanter. Budeme požadovat tento výsledek:

Obrázek 7: Sloupcový graf se čtyřmi kategoriemi.

Nejprve si vytvoříme sekvenci obsahující kategorie, které se ovšem budou opakovat, aby byl počet prvků v sekvenci totožný s počtem všech vykreslovaných hodnot. K tomuto účelu použijeme funkci repeat, která bude třikrát opakovat předaný seznam (nebo jinou sekvenci):

(def seasons (mapcat identity (repeat 3 ["jaro" "léto" "podzim" "zima"])))

Výsledkem bude sekvence s dvanácti prvky:

seasons
("jaro" "léto" "podzim" "zima" "jaro" "léto" "podzim" "zima" "jaro" "léto" "podzim" "zima")

Dále vytvoříme druhou sekvenci, tentokrát obsahující roky, pro které se má graf vykreslit. Opět získáme sekvenci s dvanácti hodnotami, tentokrát se ovšem v sekvenci opakuje každá hodnota čtyřikrát (stále opakujeme jen tři roky):

(def years (mapcat identity (repeat 4 [2016 2017 2018])))
 
years
(2016 2017 2018 2016 2017 2018 2016 2017 2018 2016 2017 2018)

A konečně následuje sekvence s vlastními hodnotami, které se mají vykreslit do grafu. Pro jednoduchost zde použijeme generátor náhodných hodnot s rovnoměrným rozdělením:

(def values (sample-uniform 12 :integers true :max 100))
 
values
(75 81 45 95 98 52 73 59 9 3 98 34)

Samotné vykreslení grafu je již poměrně snadné, ovšem nesmíme přitom zapomenout na předání již výše zmíněného parametru :group-by, aby se dosáhlo korektního seskupení hodnot podle kategorií (ostatně schválně si vyzkoušejte, jak bude graf vypadat, pokud tento parametr makru bar-chart nepředáte):

(view (bar-chart years values :group-by seasons :legend true :x-label "Rok" :y-label "Úroda"))

5. Speciální forma doto

V následujících kapitolách se poměrně často setkáme se speciální formou nazvanou doto, která se v programovacím jazyku Clojure používá pro zjednodušení volání funkcí (či metod), které mají shodný první parametr. Nejprve se ovšem podívejme na jednoduchý příklad, v němž se tato speciální forma naopak nevyužívá:

(defn -main
    "Vstupni bod do aplikace."
    [& args]
    (let [object (create-object args)]
          (do-something object)
          (do-something-else object 1)
          (do-something-else object 2)
          (do-something-else object 3)
          (do-something-else object 4)
          (do-something-else object 5)))

Programátora by zde mělo zaujmout především to, že hodnota, která je navázaná na lokální symbol object, je použita při volání dalších šesti funkcí (nebo metod, pokud by před nimi byla zapsána tečka) a to příhodně jako první parametr (což není náhoda, takto jsem si ony volané funkce schválně upravil). Jedná se tedy o opakující se kód, který není příliš přehledný a navíc opět oplývá zbytečně velkým množstvím kulatých závorek, kvůli nimž jsou LISPovské jazyky nechvalně známé :-) V tomto případě je ovšem náprava velmi snadná, protože stačí použít již v nadpisu kapitoly zmíněnou speciální formu doto a přepsat funkci -main následujícím způsobem:

(defn -main
    "Vstupni bod do aplikace."
    [& args]
    (doto (create-object args)
          (do-something)
          (do-something-else 1)
          (do-something-else 2)
          (do-something-else 3)
          (do-something-else 4)
          (do-something-else 5)))

Tato forma nejprve zavolá první funkci create-object a její výsledek postupně předá dalším čtyřem funkcím (jako první parametr). Navíc jsme se elegantně zbavili lokálního symbolu object a tím pádem i formy let.

Poznámka: doto se odlišuje od takzvaného threading makra -> v tom, že všem funkcím/metodám předává stále ten stejný objekt (jehož stav se ovšem může měnit). Naproti tomu threading makro předává další funkci výsledek funkce předchozí.

6. Spojnicový graf

Druhým typem grafu, s nímž se v dnešním článku seznámíme, je takzvaný spojnicový či liniový graf. Ten se poměrně často využívá například ve finančnictví. Na druhou stranu ovšem uvidíme, že se tento graf příliš nehodí pro zobrazení průběhu nějaké funkce – pro tento účel totiž existuje specifický typ grafu, který bude popsán později. Nejdříve se ovšem podívejme na klasický spojnicový graf. Ten se vytváří funkcí nazvanou line-chart, které se opět předají hodnoty na x-ové ose a hodnoty na ose y-ové:

(ns simple-line-chart
  (:use (incanter core stats charts)))
 
(def x (range 0 100 0.5))
(def y (map #(/ (sin %) (inc %)) x))
(view (line-chart x y))

Povšimněte si, že hodnoty vynesené na x-ovou osu nejsou čitelné – je jich příliš mnoho:

Obrázek 8: Jednoduchý spojnicový graf s výchozím popisem os.

V případě potřeby můžeme změnit rozsah hodnot na y-ové ose, a to zavoláním funkce set-y-range. Vzhledem k tomu, že prvním parametrem této funkce je objekt s grafem, můžeme využít speciální formu doto:

(view (doto (line-chart x y)
            (set-y-range -1/2 1/2)))

Nebo ještě jednodušeji:

(doto (line-chart x y)
      (set-y-range -1/2 1/2)
      view)

Obrázek 9: Změna minimální a maximální hodnoty na vertikální ose.

Dále si můžeme změnit popisky os, a to s využitím funkcí pojmenovaných set-x-label a set-y-label. Tyto funkce je opět vhodné volat přes speciální formu doto:

(view (doto (line-chart x y :title "sinc")
            (set-y-range -1/2 1/2)
            (set-x-label "t")
            (set-y-label "sinc")))

Obrázek 10: Popisky os a titulek grafu.

7. Pod kapotu Incanteru – přímé použití objektů z knihovny JFreeChart

Kromě již zmíněných funkcí set-x-label, set-y-label či set-y-range nám systém Incanter nenabízí mnoho možností, jak ovlivnit způsob vykreslení grafu. Pokud je například nutné změnit frekvenci značek na osách atd., musíme se uchýlit k přímému použití objektů z knihovny JFreeChart. V této kapitole budou ukázány jen některé možnosti, protože knihovna JFreeChart je poměrně rozsáhlá a zasloužila by si vlastní článek.

Nový příklad začneme podobně, jako příklad předchozí, tj. importem potřebných modulů a následně vytvořením sekvencí představujících hodnoty na x-ové ose a vynášené hodnoty:

(ns jfree-chart-interface
  (:use (incanter core stats charts)))
 
(def x (range 0 100 0.5))
(def y (map #(/ (sin %) (inc %)) x))

Následně vytvoříme objekt s grafem, u kterého ovšem změníme frekvenci numerických popisů na y-ové ose:

(def plot (doto (line-chart x y :title "sinc")
                (set-y-range -1/2 1/2)
                (set-x-label "t")
                (set-y-label "sinc")))

Nastavení popisků na y-ové ose zavoláním metody setTickUnit() pro objekt představující y-ovou osu (range axis) a zobrazení grafu:

(.setTickUnit (.getRangeAxis (.getPlot plot))
              (org.jfree.chart.axis.NumberTickUnit. 0.05))
(view plot)

Obrázek 11: Změna popisků na vertikální ose.

Mnohem jednodušší je další operace, která zakáže vykreslování popisků a značek na x-ové ose:

(.setVisible (.getDomainAxis (.getPlot plot)) false)
(view plot)
Poznámka: povšimněte si, že i když je Incanter naprogramován ve funkcionálním jazyce Clojure, je objekt typu plot ve skutečnosti měnitelný voláním jeho metod.

Obrázek 12: Odstranění popisků na horizontální ose.

8. Vykreslení grafu s průběhem funkce

Pro vykreslení grafu s průběhem nějaké funkce je vhodnější namísto výše popsaného liniového grafu použít graf vytvořený funkcí function-plot. Jedním z důvodů vedoucích k použití tohoto typu grafu je snadnější manipulace s popisky os. Opět se podívejme na jednoduchý příklad, v němž se tento typ grafu použije. Začneme specifikací jmenného prostoru a importem potřebných modulů:

(ns simple-function-plot
  (:use (incanter core stats charts symbolic)))

Vykreslovat budeme známou funkci sinc, takže si ji nejdříve nadefinujeme, stejně jako jakoukoli jinou funkci:

(defn sinc
    [t]
    (/ (sin t) t))

Vykreslení této funkce je až triviálně jednoduché. Konstanty –20 a 20 představují rozsah hodnot na x-ové ose:

(view (function-plot sinc -10 10))

Obrázek 13: Vykreslení průběhu funkce sinc.

Pro zajímavost se můžeme pokusit vykreslit derivaci funkce sinc. Již dopředu si řekněme, že použití deriv-fn nepovede k žádoucímu výsledku, i když derivace sinc lze vypočítat snadno:

(view (function-plot (deriv-fn [t] (/ (sin t) t) t) -20 20))

Obrázek 14: Snaha o výpočet a vykreslení derivace funkce sinc.

S využitím funkce add-function můžeme do grafu přidat průběh další funkce. Například si můžeme současně vykreslit jak původní funkci sinc, tak i její symbolicky vyjádřenou derivaci:

(doto (function-plot sinc -10 10)
      (add-function (deriv-fn [t] (/ (sin t) t) t) -10 10)
      view)

Obrázek 15: Současné vykreslení funkce i její derivace (nekorektní výsledek).

9. Vykreslení funkce i její derivace

U vykreslení derivace funkce se na chvíli zastavme. Pokusme se například vykreslit derivaci funkce sinus, a to v rozsahu 0 až π. Vykreslení samotné funkce sinus je až triviálně jednoduché:

(def pi java.lang.Math/PI)
 
(view (function-plot sin 0 pi))

Obrázek 16: Průběh funkce sin.

Derivací funkce sinus by měl být kosinus, o čemž se můžeme přesvědčit velmi snadno:

(view (function-plot (deriv-fn [t] (sin t) t) 0 pi))

Obrázek 17: Derivace funkce sin.

Nyní můžeme oba průběhy vykreslit v jediném grafu:

(doto (function-plot sin 0 pi)
      (add-function (deriv-fn [t] (sin t) t) 0 pi)
      view)

Obrázek 18: Průběh funkce sin i její derivace v jediném grafu.

Můžeme vidět, že tentokrát je výsledek korektní.

10. Numerický výpočet derivace

Pro vykreslení derivace funkce sinc bude lepší využít numerický výpočet derivace prováděný s využitím funkce nazvané derivative. Podívejme se na jednoduchý příklad, v němž opět nadefinujeme sinc a následně průběh této funkce zobrazíme současně s její derivací:

(defn sinc
    [t]
    (/ (sin t) t))
 
(doto (function-plot sinc -10 10)
      (add-function (derivative sinc) -10 10)
      view)

Obrázek 19: Funkce sinc a její derivace. Původní průběh funkce je vykreslen červeně, derivace modře.

Pro větší přehlednost je možné nadefinovat popisky os grafu:

(doto (function-plot sinc -10 10 :x-label "t" :y-label "sinc + deriv sinc")
      (add-function (derivative sinc) -10 10)
      view)

Obrázek 20: Změna popisků os grafu.

11. Vliv hodnoty dx na numerický výpočet derivace

Funkci derivative, s níž jsme se seznámili v předchozí kapitole, je možné předat nepovinný parametr pojmenovaný :dx. Tímto parametrem se specifikuje (zjednodušeně řečeno) x-ová vzdálenost mezi dvěma body na funkci v místě, kde se počítá sklon (směrnice tečny) funkce, tj. její hodnota derivace. Výchozí hodnota :dx je nastavena na 0.0001, ale můžete si snadno vyzkoušet, co se stane ve chvíli, kdy bude hodnota příliš velká a kdy se tedy sklon bude počítat na příliš vzdálených bodech (s ohledem na to, s jakou frekvencí funkce kmitá):

(doto (function-plot sinc -10 10 :x-label "t" :y-label "sinc + deriv sinc")
      (add-function (derivative sinc :dx 5) -10 10)
      view)

Obrázek 21: Příliš velká hodnota dx znehodnotí výpočet derivace (modrý průběh).

Pro ještě lepší přehled o vlivu :dx na přesnost výpočtů si ukažme graf obsahující mj. i čtyři vypočtené průběhy derivace funkce sinc. První tři průběhy s :dx postupně nastavenou na 0.0001, 1/2 a 1 lze ještě považovat za prakticky dostatečně přesné výpočty derivace, ovšem poslední průběh (fialový) již v žádném případě skutečné derivaci neodpovídá:

(doto (function-plot sinc -10 10 :x-label "t" :y-label "sinc + deriv sinc")
      (add-function (derivative sinc) -10 10)
      (add-function (derivative sinc :dx 1/2) -10 10)
      (add-function (derivative sinc :dx 1) -10 10)
      (add-function (derivative sinc :dx 5) -10 10)
      view)

Obrázek 22: Vliv postupné změny hodnoty dx při numerickém výpočtu derivace.

12. Přidání popisků do grafu

Podívejme se ještě na další zajímavou vlastnost Incanteru (kterou opět nalezneme i v Matplotlibu i dalších podobných knihovnách). Do grafu je totiž možné přidat popisky, dokonce s ukazateli (šipkami) na přesné místo, ke kterému se popisek vztahuje. V následujícím grafu jsem například vyznačil ty body na průběhu funkce sinc, v nichž by měla být derivace nulová (tečna v těchto bodech má stejný sklon, jako osa x):

Obrázek 23: Graf s přidanými popisky.

Popisky se do grafu přidají funkcí add-pointer, které je nutné předat souřadnice bodu, na který bude šipka ukazovat, a taktéž text, který se má v grafu zobrazit. V následujícím příkladu jsem nejprve provedl pomocný výpočet x-ové souřadnice bodů ±5π/2 a následně je již vynesení bodů s ukazateli do grafu snadné:

(ns add-pointer-to-plot
  (:use (incanter core stats charts optimize)))
 
(def pi java.lang.Math/PI)
 
(defn sinc
    [t]
    (/ (sin t) t))
 
(def d0 (/ (* pi 5) 2))
 
(doto (function-plot sinc -10 10 :x-label "t" :y-label "sinc + deriv sinc")
      (set-y-range -1/2 3/2)
      (add-function (derivative sinc) -10 10)
      (add-pointer 0 1 :text "deriv=0")
      (add-pointer d0 (sinc d0) :text "deriv=0")
      (add-pointer (- d0) (sinc (- d0)) :text "deriv=0")
      view)
Poznámka: v grafu jsou vyznačeny jen tři body, v nichž je derivace sinc nulová. Ve skutečnosti je však pochopitelně těchto bodů mezi –10 až 10 více. Slovy klasika: „vím o nich“.

13. Parametrický graf

Posledním typem grafu, s nímž se dnes seznámíme, je parametrický graf. Ten dokáže vykreslit průběh funkce typu x,y=f(t). Jak se však taková taková funkce vytvoří? V Clojure sice každá funkce vrací jedinou hodnotu (na rozdíl od jazyka Lua), ovšem nic nám nebrání v tom vrátit vektor obsahující dvojici návratových hodnot x a y. A právě tento způsob je využit v parametrickém grafu. Podívejme se na vykreslení jednoduché spirály:

(ns parametric-graph
  (:use (incanter core stats charts svg)))
 
 
(defn spiral
    [t]
    [(* t (cos t)) (* t (sin t))])
 
(view (parametric-plot spiral 0 (* 6 Math/PI) :x-label "x" :y-label "y"))

Obrázek 24: Spirála vykreslená předchozím příkladem.

Podobným způsobem můžeme vykreslit například Lissajousův obrazec:

(defn lis
    [t]
    [(cos (* t 3)) (sin (* t 4))])
 
(view (parametric-plot lis 0 (* 6 Math/PI) :x-label "x" :y-label "y"))

Obrázek 25: Lissajousův obrazec vykreslený předchozím příkladem.

14. 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:

15. 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. Programovací jazyk Clojure – triky při práci s řetězci
    http://www.root.cz/clanky/programovaci-jazyk-clojure-triky-pri-praci-s-retezci/
  17. Programovací jazyk Clojure – triky při práci s kolekcemi
    http://www.root.cz/clanky/programovaci-jazyk-clojure-triky-pri-praci-s-kolekcemi/
  18. Programovací jazyk Clojure – práce s mapami a množinami
    http://www.root.cz/clanky/programovaci-jazyk-clojure-prace-s-mapami-a-mnozinami/
  19. Programovací jazyk Clojure – základy zpracování XML
    http://www.root.cz/clanky/programovaci-jazyk-clojure-zaklady-zpracovani-xml/
  20. Programovací jazyk Clojure – testování s využitím knihovny Expectations
    http://www.root.cz/clanky/programovaci-jazyk-clojure-testovani-s-vyuzitim-knihovny-expectations/
  21. 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/
  22. Enlive – výkonný šablonovací systém pro jazyk Clojure
    http://www.root.cz/clanky/enlive-vykonny-sablonovaci-system-pro-jazyk-clojure/
  23. 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/
  24. Novinky v Clojure verze 1.8.0
    http://www.root.cz/clanky/novinky-v-clojure-verze-1–8–0/
  25. 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/
  26. 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/
  27. 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/
  28. Vytváříme IRC bota v programovacím jazyce Clojure
    http://www.root.cz/clanky/vytvarime-irc-bota-v-programovacim-jazyce-clojure/
  29. Gorilla REPL: interaktivní prostředí pro programovací jazyk Clojure
    https://www.root.cz/clanky/gorilla-repl-interaktivni-prostredi-pro-programovaci-jazyk-clojure/
  30. Multimetody v Clojure aneb polymorfismus bez použití OOP
    https://www.root.cz/clanky/multimetody-v-clojure-aneb-polymorfismus-bez-pouziti-oop/
  31. 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/
  32. Clojure 16: Složitější uživatelská makra
    http://www.root.cz/clanky/programovaci-jazyk-clojure-16-slozitejsi-uzivatelska-makra/
  33. Clojure 17: Využití standardních maker v praxi
    http://www.root.cz/clanky/programovaci-jazyk-clojure-17-vyuziti-standardnich-maker-v-praxi/
  34. Clojure 18: Základní techniky optimalizace aplikací
    http://www.root.cz/clanky/programovaci-jazyk-clojure-18-zakladni-techniky-optimalizace-aplikaci/
  35. Clojure 19: Vývojová prostředí pro Clojure
    http://www.root.cz/clanky/programovaci-jazyk-clojure-19-vyvojova-prostredi-pro-clojure/
  36. 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/
  37. Clojure 21: ClojureScript aneb překlad Clojure do JS
    http://www.root.cz/clanky/programovaci-jazyk-clojure-21-clojurescript-aneb-preklad-clojure-do-javascriptu/
  38. Leiningen: nástroj pro správu projektů napsaných v Clojure
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure/
  39. 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/
  40. 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/
  41. 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/
  42. 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/
  43. 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/
  44. Programovací jazyk Clojure a databáze (1.část)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-databaze-1-cast/
  45. Pluginy pro Leiningen
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-pluginy-pro-leiningen/
  46. 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/
  47. 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/
  48. 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/
  49. 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/
  50. Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure
    http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure/
  51. 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/
  52. 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/
  53. Programovací jazyk Clojure a práce s Gitem
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-prace-s-gitem/
  54. Programovací jazyk Clojure a práce s Gitem (2)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-prace-s-gitem-2/
  55. 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/
  56. Pixie: lehký skriptovací jazyk s „kouzelnými“ schopnostmi
    https://www.root.cz/clanky/pixie-lehky-skriptovaci-jazyk-s-kouzelnymi-schopnostmi/
  57. 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/
  58. Novinky v Clojure verze 1.9.0
    https://www.root.cz/clanky/novinky-v-clojure-verze-1–9–0/
  59. 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/
  60. 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/
  61. 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/
  62. Incanter: prostředí pro statistické výpočty s grafickým výstupem založené na Clojure
    https://www.root.cz/clanky/incanter-prostredi-pro-statisticke-vypocty-s-grafickym-vystupem-zalozene-na-clojure/
  63. Incanter: operace s maticemi
    https://www.root.cz/clanky/incanter-operace-s-maticemi/

16. Odkazy na Internetu

  1. Stopa (algebra)
    https://cs.wikipedia.org/wi­ki/Stopa_(algebra)
  2. Matrix calculator
    https://matrixcalc.org/en/
  3. Incanter is a Clojure-based, R-like platform for statistical computing and graphics.
    http://incanter.org/
  4. Evolution of incanter (Gource Visualization)
    https://www.youtube.com/wat­ch?v=TVfL5nPELr4
  5. Questions tagged [incanter] (na Stack Overflow)
    https://stackoverflow.com/qu­estions/tagged/incanter?sor­t=active
  6. Data Sorcery with Clojure
    https://data-sorcery.org/contents/
  7. 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
  8. Incanter Cheat Sheet
    http://incanter.org/docs/incanter-cheat-sheet.pdf
  9. 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
  10. Lisp-Stat Information
    http://homepage.cs.uiowa.e­du/~luke/xls/xlsinfo/
  11. Sample Plots in Incanter
    https://github.com/incanter/in­canter/wiki/Sample-Plots-in-Incanter#line
  12. vectorz-clj
    https://github.com/mikera/vectorz-clj
  13. vectorz – Examples
    https://github.com/mikera/vectorz-clj/wiki/Examples
  14. Array Programming
    https://en.wikipedia.org/wi­ki/Array_programming
  15. Discovering Array Languages
    http://archive.vector.org­.uk/art10008110
  16. no stinking loops – Kalothi
    http://www.nsl.com/
  17. Vector (obsahuje odkazy na články, knihy a blogy o programovacích jazycích APL, J a K)
    http://www.vector.org.uk/
  18. Colt
    http://dst.lbl.gov/ACSSoftware/colt/
  19. Parallel Colt: Open Source Libraries for High Performance Scientific and Technical Computing in Java
    http://incanter.org/docs/pa­rallelcolt/api/
  20. Processing
    https://www.processing.org/
  21. The R Project for Statistical Computing
    https://www.r-project.org/
  22. Humane test output for clojure.test
    https://github.com/pjstadig/humane-test-output
  23. iota
    https://github.com/juxt/iota
  24. 5 Differences between clojure.spec and Schema
    https://lispcast.com/clojure.spec-vs-schema/
  25. Schema: Clojure(Script) library for declarative data description and validation
    https://github.com/plumatic/schema
  26. Zip archiv s Clojure 1.9.0
    http://repo1.maven.org/ma­ven2/org/clojure/clojure/1­.9.0/clojure-1.9.0.zip
  27. Clojure 1.9 is now available
    https://clojure.org/news/2017/12/08/clo­jure19
  28. Deps and CLI Guide
    https://clojure.org/guides/dep­s_and_cli
  29. Changes to Clojure in Version 1.9
    https://github.com/clojure/clo­jure/blob/master/changes.md
  30. clojure.spec – Rationale and Overview
    https://clojure.org/about/spec
  31. Zip archiv s Clojure 1.8.0
    http://repo1.maven.org/ma­ven2/org/clojure/clojure/1­.8.0/clojure-1.8.0.zip
  32. Clojure 1.8 is now available
    http://clojure.org/news/2016/01/19/clo­jure18
  33. Socket Server REPL
    http://dev.clojure.org/dis­play/design/Socket+Server+REPL
  34. CLJ-1671: Clojure socket server
    http://dev.clojure.org/jira/browse/CLJ-1671
  35. CLJ-1449: Add clojure.string functions for portability to ClojureScript
    http://dev.clojure.org/jira/browse/CLJ-1449
  36. Launching a Socket Server
    http://clojure.org/referen­ce/repl_and_main#_launchin­g_a_socket_server
  37. API for clojure.string
    http://clojure.github.io/clo­jure/branch-master/clojure.string-api.html
  38. Clojars:
    https://clojars.org/
  39. Seznam knihoven na Clojars:
    https://clojars.org/projects
  40. Clojure Cookbook: Templating HTML with Enlive
    https://github.com/clojure-cookbook/clojure-cookbook/blob/master/07_webapps/7–11_enlive.asciidoc
  41. An Introduction to Enlive
    https://github.com/swannodette/enlive-tutorial/
  42. Enlive na GitHubu
    https://github.com/cgrand/enlive
  43. Expectations: příklady atd.
    http://jayfields.com/expectations/
  44. Expectations na GitHubu
    https://github.com/jaycfi­elds/expectations
  45. Lein-expectations na GitHubu
    https://github.com/gar3thjon3s/lein-expectations
  46. Testing Clojure With Expectations
    https://semaphoreci.com/blog/2014/09/23/tes­ting-clojure-with-expectations.html
  47. 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/
  48. Testing: One assertion per test
    http://blog.jayfields.com/2007/06/tes­ting-one-assertion-per-test.html
  49. Rewriting Your Test Suite in Clojure in 24 hours
    http://blog.circleci.com/rewriting-your-test-suite-in-clojure-in-24-hours/
  50. Clojure doc: zipper
    http://clojuredocs.org/clo­jure.zip/zipper
  51. Clojure doc: parse
    http://clojuredocs.org/clo­jure.xml/parse
  52. Clojure doc: xml-zip
    http://clojuredocs.org/clojure.zip/xml-zip
  53. Clojure doc: xml-seq
    http://clojuredocs.org/clo­jure.core/xml-seq
  54. Parsing XML in Clojure
    https://github.com/clojuredocs/guides
  55. Clojure Zipper Over Nested Vector
    https://vitalyper.wordpres­s.com/2010/11/23/clojure-zipper-over-nested-vector/
  56. Understanding Clojure's PersistentVector implementation
    http://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation
  57. Understanding Clojure's PersistentHashMap (deftwice…)
    http://blog.higher-order.net/2009/09/08/understanding-clojures-persistenthashmap-deftwice.html
  58. Assoc and Clojure's PersistentHashMap: part ii
    http://blog.higher-order.net/2010/08/16/assoc-and-clojures-persistenthashmap-part-ii.html
  59. Ideal Hashtrees (paper)
    http://lampwww.epfl.ch/pa­pers/idealhashtrees.pdf
  60. Clojure home page
    http://clojure.org/
  61. Clojure (downloads)
    http://clojure.org/downloads
  62. Clojure Sequences
    http://clojure.org/sequences
  63. Clojure Data Structures
    http://clojure.org/data_structures
  64. 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
  65. 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
  66. Clojure – Functional Programming for the JVM
    http://java.ociweb.com/mar­k/clojure/article.html
  67. Clojure quick reference
    http://faustus.webatu.com/clj-quick-ref.html
  68. 4Clojure
    http://www.4clojure.com/
  69. ClojureDoc (rozcestník s dokumentací jazyka Clojure)
    http://clojuredocs.org/
  70. Clojure (na Wikipedia EN)
    http://en.wikipedia.org/wiki/Clojure
  71. Clojure (na Wikipedia CS)
    http://cs.wikipedia.org/wiki/Clojure
  72. SICP (The Structure and Interpretation of Computer Programs)
    http://mitpress.mit.edu/sicp/
  73. Pure function
    http://en.wikipedia.org/wi­ki/Pure_function
  74. Funkcionální programování
    http://cs.wikipedia.org/wi­ki/Funkcionální_programová­ní
  75. Čistě funkcionální (datové struktury, jazyky, programování)
    http://cs.wikipedia.org/wi­ki/Čistě_funkcionální
  76. 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
  77. Clojure Macro Tutorial (Part II: The Compiler Strikes Back)
    http://www.learningclojure­.com/2010/09/clojure-macro-tutorial-part-ii-compiler.html
  78. Clojure Macro Tutorial (Part III: Syntax Quote)
    http://www.learningclojure­.com/2010/09/clojure-macro-tutorial-part-ii-syntax.html
  79. Tech behind Tech: Clojure Macros Simplified
    http://techbehindtech.com/2010/09/28/clo­jure-macros-simplified/
  80. Fatvat – Exploring functional programming: Clojure Macros
    http://www.fatvat.co.uk/2009/02/clo­jure-macros.html
  81. Eulerovo číslo
    http://cs.wikipedia.org/wi­ki/Eulerovo_číslo
  82. List comprehension
    http://en.wikipedia.org/wi­ki/List_comprehension
  83. List Comprehensions in Clojure
    http://asymmetrical-view.com/2008/11/18/list-comprehensions-in-clojure.html
  84. Clojure Programming Concepts: List Comprehension
    http://en.wikibooks.org/wi­ki/Clojure_Programming/Con­cepts#List_Comprehension
  85. Clojure core API: for macro
    http://clojure.github.com/clo­jure/clojure.core-api.html#clojure.core/for
  86. cirrus machina – The Clojure for macro
    http://www.cirrusmachina.com/blog/com­ment/the-clojure-for-macro/
  87. Riastradh's Lisp Style Rules
    http://mumble.net/~campbe­ll/scheme/style.txt
  88. Dynamic Languages Strike Back
    http://steve-yegge.blogspot.cz/2008/05/dynamic-languages-strike-back.html
  89. Scripting: Higher Level Programming for the 21st Century
    http://www.tcl.tk/doc/scripting.html
  90. Java Virtual Machine Support for Non-Java Languages
    http://docs.oracle.com/ja­vase/7/docs/technotes/gui­des/vm/multiple-language-support.html
  91. Třída java.lang.String
    http://docs.oracle.com/ja­vase/7/docs/api/java/lang/Strin­g.html
  92. Třída java.lang.StringBuffer
    http://docs.oracle.com/ja­vase/7/docs/api/java/lang/Strin­gBuffer.html
  93. Třída java.lang.StringBuilder
    http://docs.oracle.com/ja­vase/7/docs/api/java/lang/Strin­gBuilder.html
  94. StringBuffer versus String
    http://www.javaworld.com/ar­ticle/2076072/build-ci-sdlc/stringbuffer-versus-string.html
  95. Threading macro (dokumentace k jazyku Clojure)
    https://clojure.github.io/clo­jure/clojure.core-api.html#clojure.core/->
  96. Understanding the Clojure → macro
    http://blog.fogus.me/2009/09/04/un­derstanding-the-clojure-macro/
  97. clojure.inspector
    http://clojure.github.io/clo­jure/clojure.inspector-api.html
  98. The Clojure Toolbox
    http://www.clojure-toolbox.com/
  99. Unit Testing in Clojure
    http://nakkaya.com/2009/11/18/unit-testing-in-clojure/
  100. Testing in Clojure (Part-1: Unit testing)
    http://blog.knoldus.com/2014/03/22/tes­ting-in-clojure-part-1-unit-testing/
  101. API for clojure.test – Clojure v1.6 (stable)
    https://clojure.github.io/clo­jure/clojure.test-api.html
  102. Leiningen: úvodní stránka
    http://leiningen.org/
  103. Leiningen: Git repository
    https://github.com/techno­mancy/leiningen
  104. leiningen-win-installer
    http://leiningen-win-installer.djpowell.net/
  105. Clojure.org: Vars and the Global Environment
    http://clojure.org/Vars
  106. Clojure.org: Refs and Transactions
    http://clojure.org/Refs
  107. Clojure.org: Atoms
    http://clojure.org/Atoms
  108. Clojure.org: Agents as Asynchronous Actions
    http://clojure.org/agents
  109. Transient Data Structures
    http://clojure.org/transients
Našli jste v článku chybu?