Hlavní navigace

Tvorba grafů v systému Incanter (pokračování)

Pavel Tišnovský

Ve čtvrtém článku o systému Incanter budeme pokračovat tématem, kterému jsme se začali věnovat minule. Popíšeme si totiž způsob tvorby dalších typů grafů, které Incanter podporuje kromě již zmíněného sloupcového a spojnicového grafu.

Doba čtení: 25 minut

11. Vylepšený histogram

12. Teplotní mapa (heatmap)

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

14. Odkazy na předchozí části seriálu o jazyku Clojure

15. Odkazy na Internetu

1. Tvorba grafů v systému Incanter (pokračování)

Ve čtvrté části miniseriálu o projektu Incanter navážeme na část předchozí, v níž jsme si popsali tvorbu základních typů grafů. Především se jednalo o klasické sloupcové grafy, které mohou ve své nejjednodušší podobě zobrazit jedinou kategorii hodnot. Takový graf je zobrazen na prvním screenshotu pod tímto odstavcem:

Obrázek 1: Sloupcový graf s jedinou kategorií (jak jste správně upozornili u předchozího článku, vstupem jsou sice celočíselné hodnoty, ovšem popiska y-ové osy obsahuje desetinná čísla).

Sloupcové grafy ovšem mohou být i složitější, protože dokážou zobrazit větší množství kategorií. Opět si jen ve stručnosti ukažme, jak takový graf vypadá. Na tomto grafu jsou zobrazeny čtyři kategorie, z nichž každá odpovídá nějaké hodnotě pro zvolené roční období (jaro, léto, podzim, zima):

Obrázek 2: Nepatrně složitější sloupcový graf se čtyřmi kategoriemi.

Dalším typem grafu, se kterým jsme se minule setkali, jsou takzvané spojnicové grafy. I tyto grafy se používají pro zobrazení hodnot z jedné kategorie, popř. z většího množství kategorií. Nejjednodušší graf tohoto typu je zobrazen na třetím screenshotu:

Obrázek 3: Spojnicový graf.

Pro vykreslení grafu s průběhem nějaké funkce je vhodnější namísto výše zmíněného liniového (spojnicové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. Tento typ grafu jsme mj. použili pro zobrazení průběhu funkce sinc i její derivace. Navíc jsme do grafu ručně vložili ukazatele s popiskami zajímavých oblastí:

Obrázek 4: Graf s průběhem funkce a její derivace s přidanými popisky.

Dalším typem grafu, s nímž jsme se ve stručnosti seznámili minule, je parametrický graf. Ten dokáže vykreslit průběh funkce typu x,y=f(t), což je ukázáno na dalším screenshotu:

Obrázek 5: Lissajousův obrazec vykreslený s pomocí parametrického grafu.

Ve skutečnosti mohou být parametrické grafy ještě složitější, takže si je podrobněji popíšeme v navazující kapitole.

2. Přidání druhé funkce do parametrického grafu

Pro krátké zopakování si ukažme, jakým způsobem můžeme vykreslit graf se spirálou. Samotná spirála je definována ve funkci spiral:

(defn spiral
    [t]
    [(* t (cos t)) (* t (sin t))])

O vykreslení spirály v parametrickém grafu se postará funkce nazvaná parametric-plot:

(-> (parametric-plot spiral 0 (* 6 Math/PI) :x-label "x" :y-label "y")
    view)

Výsledek může vypadat následovně:

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

Do grafu ovšem můžeme snadno přidat další průběh, například křivku tvořenou trajektorií rotujícího bodu, přičemž střed rotace se pohybuje po spirále. Tato trajektorie je definována v další funkci (povšimněte si, že takto funkce opět vrací vektor s dvojicí souřadnic x a y):

(defn spiral-2
    [t]
    [(+ (* t (cos t))
        (* 0.4 (sin (* 20 t))))
     (+ (* t (sin t))
        (* 0.4 (cos (* 20 t))))])

Nový průběh do parametrického grafu přidáme funkcí nazvanou add-parametric. Tato funkce vrací modifikovaný objekt představující graf, takže je možné v případě potřeby přidat i třetí, popř. další průběh:

(-> (parametric-plot spiral 0 (* 6 Math/PI) :x-label "x" :y-label "y")
    (add-parametric spiral-2 0 (* 6 Math/PI))
    view)

Obrázek 6: Parametrický graf se zobrazením průběhů dvou parametrických funkcí.

3. Použití uzávěrů pro zjednodušení deklarace funkcí pro parametrický graf

Jen pro zajímavost si ukažme, jakým způsobem si můžeme zjednodušit deklaraci funkcí, které mají stejný tvar (zápis), ovšem liší se hodnotou nějakého parametru, který je při vykreslování konstantní. Představme si například, že budeme chtít vykreslovat různé tvary založené na Lissajousových obrazcích zmíněných minule. V programovacím jazyku Clojure (ale samozřejmě nejenom v něm) je možné pro tento účel použít uzávěry (closure), což jsou funkce (typicky anonymní), které na sebe mají navázánu alespoň jednu tzv. volnou proměnnou. Uzávěr sloužící pro generování funkcí, které se mají vykreslit, se v Clojure vytvoří překvapivě snadno:

(defn generate-shape-function
    [xt yt]
    (fn [t]
        [(cos (* t xt))
         (sin (* t yt))]))

Díky tomuto „konstruktoru funkcí“ si můžeme nechat vygenerovat další tři funkce, které již budou akceptovat jediný parametr t a každá z nich na sebe bude mít navázána odlišné hodnoty xt a yt:

(def shape-1
    (generate-shape-function 1 2))
 
(def shape-2
    (generate-shape-function 2 1))
 
(def shape-3
    (generate-shape-function 1/3 3/2))

Všechny tři takto vytvořené funkce si můžeme nechat vykreslit:

(-> (parametric-plot shape-1 0 (* 2 Math/PI) :x-label "x" :y-label "y")
    view)
 
(-> (parametric-plot shape-2 0 (* 2 Math/PI) :x-label "x" :y-label "y")
    view)
 
(-> (parametric-plot shape-3 0 (* 2 Math/PI) :x-label "x" :y-label "y")
    view)

Obrázek 7: Průběh parametrické funkce shape-1.

Obrázek 8: Průběh parametrické funkce shape-2.

Obrázek 9: Průběh parametrické funkce shape-3.

A samozřejmě nám nic nebrání si nechat vykreslit všechny tři průběhy do jediného grafu:

(-> (parametric-plot shape-1 0 (* 2 Math/PI) :x-label "x" :y-label "y")
    (add-parametric shape-2 0 (* 2 Math/PI))
    (add-parametric shape-3 0 (* 2 Math/PI))
    view)

Obrázek 10: Všech tří funkcí shape-1, shape-2 a shape-3.

4. Graf tvořený množinou bodů [x, y]

Minule popsané liniové (spojnicové) grafy byly určeny pro zobrazení série hodnot. Tyto grafy byly doplněny možností zobrazení průběhu funkce, a to bez nutnosti explicitního výpočtu jednotlivých hodnot pro graf. Podobně je tomu u výše zmíněných parametrických grafů (určených pro vykreslení průběhu funkce), k nimž existuje jako alternativa takzvaný xy-graf sloužící pro vykreslení série bodů v rovině, popř. série bodů pospojovaných úsečkami. Podívejme se nejprve na zcela nejjednodušší příklad, v němž vykreslíme sérii bodů [x,y], přičemž hodnoty x budou generovány standardní funkcí range a hodnoty y se z první sekvence vypočítají aplikací funkce sin (v tomto případě se jedná o rozšíření Incanteru, který dokáže aplikovat funkci na všechny prvky sekvence):

(def x (range 0 (* 2 Math/PI) 0.1))
(def y (sin x))
 
(-> (xy-plot x y)
    view)

Výsledek bude vypadat podle očekávání:

Obrázek 11: Vykreslení série bodů [x,y] propojených úsečkami.

Poznámka: ve skutečnosti je ovšem chování grafu xy-plot poněkud složitější, což si vysvětlíme v navazující kapitole.

5. Automatické řazení bodů podle jejich x-ové souřadnice

V předchozím příkladu se podle očekávání vykreslila sinusovka, takže by se mohlo zdát, že funkce xy-plot jednoduše vykreslí sekvenci bodů [x,y] v takovém pořadí, v jakém je získá na vstupu. Ve skutečnosti tomu tak ovšem implicitně není, o čemž se velmi snadno přesvědčíme při pokusu o vykreslení kružnice. První verze příkladu pro vykreslení kružnice s využitím xy-grafu by mohla vypadat následovně:

(def t (range 0 (* 2 Math/PI) 0.1))
(def x (cos t))
(def y (sin t))
 
(-> (xy-plot x y)
    view)

Výsledek bude přinejmenším překvapující:

Obrázek 12: Výsledek prvního pokusu o vykreslení kružnice.

Při pohledu na předchozí screenshot vás možná napadlo, kde problém vznikl: Incanter seřadil obě sekvence podle x-ové souřadnice, takže na přeskáčku vykresloval horní a spodní oblouk kružnice. U sinusovky jsme si toho nevšimli, protože hodnoty x byly rostoucí.

Oprava předchozího příkladu je jednoduchá – postačuje výchozí řazení zakázat volitelným parametrem pojmenovaným :auto-sort, kterému předáme hodnotu false nebo nil:

(def t (range 0 (* 2 Math/PI) 0.1))
(def x (cos t))
(def y (sin t))
 
(-> (xy-plot x y :auto-sort false)
    view)

Obrázek 13: Výsledek druhého pokusu o vykreslení kružnice.

6. Lorenzův atraktor

Poměrně vděčným příkladem funkce zobrazené ve 2D nebo dokonce ve 3D prostoru je dynamický systém s takzvaným podivným atraktorem, který je pojmenovaný Lorenzův atraktor podle svého objevitele. Tento systém sestávající ze tří dynamických rovnic použil Edward Lorenz v roce 1963 při simulaci vývoje počasí (resp. ve velmi zjednodušeném modelu počasí). Na tomto systému byla také numericky a analyticky ověřena velká citlivost na počáteční podmínky (někdy také nazývaná „motýlí efekt“). Pro upřesnění je však nutné říci, že při simulaci na počítači vlastně získáme atraktor, jenž je periodický. Je to z toho důvodu, že pro zobrazení číselných hodnot je použito konečného počtu bitů, z toho nutně vyplývá, že se po určitém počtu kroků (který je však obrovský, takže tento jev mnohdy nezaregistrujeme) začne dráha Lorenzova atraktoru překrývat. V matematicky přesném modelu však tato situace nenastane, každá smyčka funkce bude mít unikátní tvar a dráhy se nebudou překrývat, pouze protínat. Diferenciální rovnice Lorenzova atraktoru mají po převodu na diferenční tvar následující formát:

dx/dt = σ (y-x)
dy/dt = x(ρ - z) - y
dz/dt = xy - Βz

Takže pro iterativní (samozřejmě že nepřesný) výpočet můžeme pracovat s následujícími vztahy, které pro dostatečně malé dt vedou k výpočtu bodů ležících na Lorenzově atraktoru:

xn+1 = xn + (σ (y-x)) dt
yn+1 = yn + (x(ρ – z) – y) dt
zn+1 = zn + (xy – Βz) dt

Obrázek 14: Lorenzův atraktor vykreslený ve 3D grafu s využitím knihovny Matplotlib.

7. Vykreslení Lorenzova atraktoru v ploše

O vykreslení Lorenzova atraktoru se samozřejmě můžeme pokusit i v systému Incanter. Zvolíme přitom funkcionální způsob výpočtu, v němž využijeme funkci vyššího řádu nazvanou jednoduše iterate. Této funkci se předá jiná funkce f a počáteční parametry této funkce. Funkce f se s těmito parametry zavolá a výsledek (vektor) se znovu použije pro volání funkce f atd. atd. Mezivýsledky výpočtu jsou současně výslednou hodnotou funkce iterate. Ovšem iterate ve skutečnosti vrací nekonečnou a současně i línou sekvenci, což znamená, že se zmíněná funkce f bude volat jen ve chvíli, kdy skutečně budeme potřebovat využít její výsledky. Celý výpočet je založen na next-values, tj. funkce pro výpočet jedné iterace Lorenzova atraktoru na základě rovnic z předchozí kapitoly:

(defn next-values
    [[x y z]]
    (let [xd (* s (- y x))
          yd (- (* r x) y (* x z))
          zd (- (* x y) (* b z))]
         [(+ x (* xd dt))
          (+ y (* yd dt))
          (+ z (* zd dt))]))
Poznámka: povšimněte si, jak se dá elegantně přistupovat k prvkům vektoru, který je jediným parametrem této funkce.

Výpočet nekonečné lazy sekvence se všemi body Lorenzova atraktoru:

(def lorenz (iterate next-values [0.0, 1.0, 1.05]))

Ve skutečnosti však samozřejmě musíme pracovat jen s konečným počtem hodnot, které získáme například funkcí take:

(def values (take n lorenz))

Zbývá již jen získat x-ové souřadnice a y-ové souřadnice:

(def x (map first values))
 
(def y (map second values))

Které již následně umíme vykreslit:

(-> (xy-plot x y :auto-sort false)
    view)

Obrázek 15: Lorenzův atraktor vykreslený podle předchozího postupu knihovnou Incanter.

8. Úplný zdrojový kód pro vykreslení Lorenzova atraktoru v ploše

Pro úplnost následuje výpis úplného zdrojového kódu určeného pro vykreslení Lorenzova atraktoru v ploše podle popisu uvedeného v předchozí kapitole:

(ns xy-plot-lorenz
  (:use (incanter core stats charts svg)))
 
 
(def s 10)
(def r 28)
(def b 2.667)
 
; krok (změna času)
(def dt 0.01)
 
; celkový počet vypočtených bodů na Lorenzově atraktoru
(def n 10000)
 
; funkce pro výpočet dalšího bodu Lorenzova atraktoru
(defn next-values
    [[x y z]]
    (let [xd (* s (- y x))
          yd (- (* r x) y (* x z))
          zd (- (* x y) (* b z))]
         [(+ x (* xd dt))
          (+ y (* yd dt))
          (+ z (* zd dt))]))
 
; vlastní výpočet atraktoru -> nekonečná lazy sekvence
(def lorenz (iterate next-values [0.0, 1.0, 1.05]))
 
; vykreslovat budeme jen konečný počet bodů
(def values (take n lorenz))
 
; x-ové souřadnice
(def x (map first values))
 
; y-ové souřadnice
(def y (map second values))
 
; vykreslení a zobrazení grafu
(-> (xy-plot x y :auto-sort false)
    view)

9. Přidání bodů a úseček do grafu

Velmi snadno můžeme do existujícího grafu typu xy přidat další sérii bodů, které mohou být skutečně vykresleny jako izolované body nebo mohou být spojeny úsečkami (což již známe z předchozích kapitol). Předchozí příklad si můžeme zobecnit a ukázat si, jak Lorenzův atraktor reaguje na situaci, kdy má nepatrně odlišné počáteční podmínky:

(ns xy-plot-lorenz
  (:use (incanter core stats charts svg)))
 
 
(def s 10)
(def r 28)
(def b 2.667)
 
; krok (změna času)
(def dt 0.01)
 
; celkový počet vypočtených bodů na Lorenzově atraktoru
(def n 2000)
 
; funkce pro výpočet dalšího bodu Lorenzova atraktoru
(defn next-values
    [[x y z]]
    (let [xd (* s (- y x))
          yd (- (* r x) y (* x z))
          zd (- (* x y) (* b z))]
         [(+ x (* xd dt))
          (+ y (* yd dt))
          (+ z (* zd dt))]))
 
(defn compute-lorenz-attractor
    [x0 y0 z0 n]
    (let [lorenz (iterate next-values [x0 y0 z0])
          values (take n lorenz)]
          values))
 
(defn x-vals
    [coordinates]
    (map first coordinates))
 
(defn y-vals
    [coordinates]
    (map second coordinates))
 
; dva atraktory, které se nepatrně liší počáteční podmínku
(def attractor1 (compute-lorenz-attractor 0.0 1.0 1.05 n))
(def attractor2 (compute-lorenz-attractor 0.01 1.0 1.05 n))
 
; vykreslení a zobrazení grafu
(-> (xy-plot   (x-vals attractor1) (y-vals attractor1) :auto-sort false)
    (add-lines (x-vals attractor2) (y-vals attractor2) :auto-sort false)
    view)

Pokud budou body druhého průběhu spojeny úsečkami, získáme tento výsledek:

Obrázek 16: Dva Lorenzovy atraktory, které mají nepatrně odlišné počáteční podmínky.

Ovšem můžeme si taktéž nechat vykreslit pouze body a nespojovat je úsečkami:

Obrázek 17: Druhý průběh je vykreslen pouze jako série bodů bez spojení úsečkami.

10. Vykreslení jednoduchého histogramu

Dalším typem grafu, který je možné při použití knihovny incanter použít, je histogram. Ten se vykresluje funkcí pojmenovanou logicky histogram. Povinným parametrem jsou podle očekávání data, která se mají do histogramu vykreslit, ovšem funkce histogram podporuje i další nepovinné parametry, zejména parametr pojmenovaný :density řídicí normalizaci histogramu. Dalším mnohdy důležitým nepovinným parametrem je :nbins, jehož hodnotou se řídí šířka intervalů (tříd), tj. nepřímo počet sloupců v histogramu. Podívejme se na způsob vykreslení histogramu pro zobrazení frekvence součtu hodnot po hodu tří kostek. Výsledek by se měl (velmi zhruba) blížit normálnímu rozložení:

(ns histogram-A
  (:use (incanter core stats charts svg)))
 
(def hody-kostkou   (take 5000 (repeatedly #(inc (rand-int 6)))))
(def hody-kostkou-2 (take 5000 (repeatedly #(inc (rand-int 6)))))
(def hody-kostkou-3 (take 5000 (repeatedly #(inc (rand-int 6)))))
 
(view (histogram (map #(+ %1 %2 %3) hody-kostkou hody-kostkou-2 hody-kostkou-3)))

Histogram zobrazuje ve výchozím nastavení pouze deset tříd, což je při vizualizaci hodů kostkou málo (ideálně potřebujeme zobrazit frekvence součtů pro hodnoty 3 až 18:

Obrázek 18: Základní histogram s deseti intervaly (třídami).

Počet tříd můžeme zvýšit na osmnáct následujícím způsobem:

(view (histogram (map #(+ %1 %2 %3) hody-kostkou hody-kostkou-2 hody-kostkou-3) :nbins 18))

Povšimněte si, že výsledek příliš neodpovídá očekávání, protože v některých intervalech nemáme (vlivem rozdělení) žádnou hodnotu. Tato situace pravděpodobně nemá při použití funkce histogram žádné rozumné řešení:

Obrázek 19: Histogram s osmnácti třídami.

11. Vylepšený histogram

Funkce histogram použitá v předchozí kapitole má i další nepříjemné chování a především není příliš konfigurovatelná. Pokud budete chtít s histogramy pracovat častěji, může být výhodnější použít řešení popsané na stránce https://stackoverflow.com/qu­estions/27991054/center-incanter-histogram-x-axis-tick-marks-directly-underneath-bars#27992128, kde je histogram nejprve spočítán a potom vykreslen pomocí běžného sloupcového grafu. Ukažme si tedy, jak je možné zobrazit výsledek hodů třemi kostkami lepším způsobem:

(ns histogram-A
  (:use (incanter core stats charts svg)))
 
(def hody-kostkou   (take 5000 (repeatedly #(inc (rand-int 6)))))
(def hody-kostkou-2 (take 5000 (repeatedly #(inc (rand-int 6)))))
(def hody-kostkou-3 (take 5000 (repeatedly #(inc (rand-int 6)))))
 
(defn bar-chart-histogram
    [values]
    (let [freq (frequencies values)
          f    #(freq % 0)
          ks   (keys freq)
          a    (apply min ks)
          b    (apply max ks)
          x-values (range a (inc b))
          x-labels (map str x-values)
          y-values (map f x-values)]
      (bar-chart x-labels y-values)))
 
(view (bar-chart-histogram (map #(+ %1 %2 %3) hody-kostkou hody-kostkou-2 hody-kostkou-3)))

Obrázek 20: Výsledek hodů třemi kostkami zobrazený ve vylepšeném histogramu.

12. Teplotní mapa (heatmap)

V případě, že je nutné nějakým způsobem zobrazit funkci typu z=f(x,y), je nutné použít buď nějakou formu 3D grafu nebo takzvanou teplotní mapu (heat map, heatmap). I ta je v systému Incanter podporována, o čemž se můžeme snadno přesvědčit:

(ns heat-map-chart
  (:use (incanter core stats charts svg)))
 
(defn f
    [x y]
    (sin (sqrt (plus (sq x) (sq y)))))

Zobrazení průběhu funkce f pro rozsah x=(-10..10) a y=(-15..15) provedeme takto:

(view (heat-map f -10 10 -15 15))

Obrázek 21: Teplotní mapa zobrazená výchozím algoritmem.

Pěknější je, alespoň podle mého názoru, vypnutí barvové palety a zobrazení teplotní mapy pouze v odstínech šedi (problém spočívá v tom, jak se mapují barvy z výchozí barvové palety Incanteru). Výsledek s teplotní mapou ve stupních šedi může vypadat následovně:

(view (heat-map f -10 10 -10 10 :color? false))

Obrázek 22: Mnohem hezčí je použití odstínů šedi.

Poznámka: pokud budete potřebovat pracovat s grafy častěji a pokud máte větší požadavky na jejich modifikaci, je pravděpodobně lepší použít Matplotlib a tudíž Python, popř. systém R. O Matplotlibu jsem se zmiňoval na „konkurenčním“ serveru mojefedora.cz, ovšem rozšířená verze těchto článků pravděpodobně vyjde i zde na Rootu.

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

# Demonstrační příklad Popis Cesta
1 01_parametric_plot_A.clj parametrická funkce https://github.com/tisnik/incanter-examples/blob/master/incanter-4/01_parametric_plot_A.clj
2 02_parametric_plot_B.clj parametrická funkce https://github.com/tisnik/incanter-examples/blob/master/incanter-4/02_parametric_plot_B.clj
3 03_xy_plot.clj graf z bodů propojených úsečkami https://github.com/tisnik/incanter-examples/blob/master/incanter-4/03_xy_plot.clj
4 04_Lorenz_attractor_A.clj Lorenzův atraktor, první varianta https://github.com/tisnik/incanter-examples/blob/master/incanter-4/04_Lorenz_attractor_A.clj
5 05_Lorenz_attractor_B.clj Lorenzův atraktor, druhá varianta https://github.com/tisnik/incanter-examples/blob/master/incanter-4/05_Lorenz_attractor_B.clj
6 06_Lorenz_attractor_C.clj Lorenzův atraktor, třetí varianta https://github.com/tisnik/incanter-examples/blob/master/incanter-4/06_Lorenz_attractor_C.clj
7 07_histogram_A.clj histogram vykreslený standardní funkcí https://github.com/tisnik/incanter-examples/blob/master/incanter-4/07_histogram_A.clj
8 08_histogram_B.clj vylepšené vykreslení histogramu https://github.com/tisnik/incanter-examples/blob/master/incanter-4/08_histogram_B.clj
9 09_heat_map.clj teplotní mapa https://github.com/tisnik/incanter-examples/blob/master/incanter-4/09_heat_map.clj

14. Odkazy na předchozí části seriálu o programovacím jazyku Clojure

  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/
  64. Tvorba jednoduchých grafů v systému Incanter
    https://www.root.cz/clanky/tvorba-jednoduchych-grafu-v-systemu-incanter/

15. 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
  110. Center Incanter histogram x-axis tick marks directly underneath bars
    https://stackoverflow.com/qu­estions/27991054/center-incanter-histogram-x-axis-tick-marks-directly-underneath-bars#27992128
Našli jste v článku chybu?