Obsah
1. Enlive – výkonný šablonovací systém pro jazyk Clojure (dokončení)
2. Vytvoření tabulky v HTML s využitím snippetu
3. Použití knihovny Enlive pro získávání dat z HTML stránek
4. Příklad enlive5 – použití funkcí html-resource a select
5. Příklad enlive6 – threading makro jako cesta k čitelnějšímu zdrojovému kódu
6. Příklad enlive7 – příklad použití speciální formy doto
7. Další typy selektorů nabízené knihovnou Enlive
8. Příklad enlive8 – použití :> a (attr=) ve funkci select
9. Repositář s dnešními demonstračními příklady
10. Odkazy na předchozí části tohoto seriálu
1. Enlive – výkonný šablonovací systém pro jazyk Clojure (dokončení)
V předchozí části seriálu o programovacím jazyce Clojure i o knihovnách, které mohou zjednodušit a současně i zlevnit vývoj aplikací vytvářených v tomto programovacím jazyku, jsme se seznámili s některými principy, na nichž je postavena knihovna pojmenovaná Enlive. Tuto knihovnu je možné použít několika způsoby: jak pro generování dynamických HTML stránek s využitím HTML šablony a sady funkcionálně zapsaných transformačních pravidel (v nichž jsou použity takzvané selektory), tak i pro „vyzobávání“ dat z existujících HTML stránek. Například je relativně jednoduché programově načíst úvodní stránku Roota a následně z ní získat nadpisy všech článků, zpráviček atd. Právě s touto poměrně zajímavou (a pro některé aplikace i velmi praktickou) problematikou se seznámíme v navazujících kapitolách, nejprve však dokončíme problematiku takzvaných snippetů.
2. Vytvoření tabulky v HTML s využitím snippetu
V posledním demonstračním příkladu, který byl popsán na samotném konci předchozí části seriálu, byly použity takzvané „snippety“ umožňující v generované HTML stránce opakovat elementy (s jinými daty). Připomeňme si, že u každého snippetu se nějakým selektorem specifikuje počáteční a koncový element v HTML šabloně a poté již snippet dokáže opakovat tu část HTML stránky, která se nachází uvnitř specifikovaných elementů. Tento postup můžeme využít i pro tvorbu tabulek, což je s velkou pravděpodobností nejčastější způsob zobrazení obsahu nějaké sekvence, tj. v pojetí Clojure typicky seznamu či vektoru. Právě tímto způsobem vytvořený snippet využijeme v dnešním prvním demonstračním příkladu, v němž se vytvoří HTML stránka obsahující herecké obsazení v divadelní hře „Vražda v salonním coupé“.
Kostra projektu demonstračního příkladu se vygeneruje jednoduše:
lein new app
Projektový soubor je nutné upravit takovým způsobem, aby se při spuštění aplikace mohlo pracovat i s knihovnou Enlive:
(defproject enlive4 "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.6.0"] [enlive "1.1.1"]] :main ^:skip-aot enlive4.core :target-path "target/%s" :profiles {:uberjar {:aot :all}})
Následuje ukázka šablony uložené v adresáři resources. Povšimněte si, že šablona je oproti předchozím příkladům upravena. Především v ní můžeme nalézt základ HTML tabulky, tabulka samotná má ID nastaveno na „roles“, jediný řádek tabulky pak má ID nastaveno na „role“. Na tomto řádku se nachází dvě buňky, první má ID „actor“ a druhá „character“. Tabulka je tak vlastně samopopisná:
<html> <head> <title>Testovaci stranka</title> <meta name="Author" content="Pavel Tisnovsky"> <meta name="Generator" content="vim"> </head> <body> <h1>Hra <span></span></h1> <table id="roles"> <tr id="role"> <td id="actor">herec</td> <td id="character">postava</td> </tr> </table> <div>Pokracovani</div> </body> </html>
Zdrojový kód demonstračního příkladu uložený v souboru src/enlive4/core.clj:
(ns enlive4.core (:gen-class)) (require '[net.cgrand.enlive-html :as html]) (def roles [ {:actor-name "Zdeněk Svěrák" :character "inspektor Trachta "} {:actor-name "Petr Brukner" :character "praktikant Hlaváček"} {:actor-name "Miloň Čepelka" :character "praktikant Hlaváček"} {:actor-name "Bořivoj Penc" :character "továrník Bierhanzel"} {:actor-name "Jaroslav Weigel" :character "továrník Bierhanzel"} {:actor-name "Jan Hraběta" :character "továrník Meyer"} {:actor-name "Václav Kotek" :character "steward"} {:actor-name "Genadij Rumlena" :character "steward"}]) (def vrazda-v-salonnim-coupe {:title "Vražda v salonním coupé" :roles roles }) (html/defsnippet one-record "test.html" {[:#role] ; zacatek [:#role]} ; konec [record] [:#actor] (html/content (:actor-name record)) [:#character] (html/content (:character record))) (html/deftemplate test-page "test.html" [data-for-page] [:title] (html/content (:title data-for-page)) [:h1 :span] (html/content (:title data-for-page)) [:#roles] (html/content (map one-record (:roles data-for-page))) ; vnitrek odstavce bude duplikovan ) (defn -main [& args] (println (reduce str (test-page vrazda-v-salonnim-coupe))))
Po spuštění tohoto příkladu by se měla na standardním výstupu objevit následující HTML stránka:
<html> <head> <title>Vražda v salonním coupé</title> <meta content="Pavel Tisnovsky" name="Author" /> <meta content="vim" name="Generator" /> </head> <body> <h1>Hra <span>Vražda v salonním coupé</span></h1> <table id="roles"><tr id="role"> <td id="actor">Zdeněk Svěrák</td> <td id="character">inspektor Trachta </td> </tr><tr id="role"> <td id="actor">Petr Brukner</td> <td id="character">praktikant Hlaváček</td> </tr><tr id="role"> <td id="actor">Miloň Čepelka</td> <td id="character">praktikant Hlaváček</td> </tr><tr id="role"> <td id="actor">Bořivoj Penc</td> <td id="character">továrník Bierhanzel</td> </tr><tr id="role"> <td id="actor">Jaroslav Weigel</td> <td id="character">továrník Bierhanzel</td> </tr><tr id="role"> <td id="actor">Jan Hraběta</td> <td id="character">továrník Meyer</td> </tr><tr id="role"> <td id="actor">Václav Kotek</td> <td id="character">steward</td> </tr><tr id="role"> <td id="actor">Genadij Rumlena</td> <td id="character">steward</td> </tr></table> <div>Pokracovani</div> </body> </html>
Povšimněte si toho, že formát výstupu není zcela přesný (uzavírací tag pro řádek tabulky není oddělen od otevíracího tagu následujícího řádku), nicméně základní struktura šablony zůstala zachována.
3. Použití knihovny Enlive pro získávání dat z HTML stránek
Knihovnu Enlive lze použít i pro získávání dat z HTML stránek. S využitím funkce net.cgrand.enlive-html/html-resource je totiž možné načíst stránku a provést její zpracování do interní podoby, v níž je stránka reprezentována formou stromu, kde jednotlivé uzly mají přiřazené atributy, poduzly a popř. i obsah (s podobným formátem jsme se již setkali při zpracování XML). Jedná se tedy o obdobu DOMu, což mj. znamená, že pro získávání dat se nepoužívá klasický parsing či regulární výrazy, ale takzvané selektory vzdáleně připomínající XPath (ne syntaxí, ale sémantikou). Druhou důležitou funkcí je funkce nazvaná net.cgrand.enlive-html/select, která na základě zadaného selektoru dokáže vrátit odpovídající uzel či sekvenci uzlů. S vrácenými daty lze provádět operace typu „získej n-tý prvek sekvence“, „získej data uložená v atributu :content“ apod. Některé z těchto možností si ukážeme v demonstračních příkladech.
V trojici příkladů bude použita tato HTML stránka, která bude sloužit jako vstup:
<html> <head> <title>Test page</title> <meta name="Author" content="Pavel Tisnovsky"> <meta name="Generator" content="vim"> </head> <body> <h1>Lorem Ipsum</h1> <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</div> <h1>Second paragraph</h1> <div>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</div> <h1>Third paragraph</h1> </body> </html>
4. Příklad enlive5 – použití funkcí html-resource a select
V demonstračním příkladu nazvaném enlive5 je použita funkce net.cgrand.enlive-html/html-resource, která dokáže načíst stránku uloženou jak na lokálním disku, tak i na zadaném URL. Po načtení je stránka zparsována a převedena do výše zmíněné stromové body, která má v tomto konkrétním případě tvar (každý tag obsahuje své symbolické jméno, množinu atributů, obsah a pod-uzly):
({:tag :html, :attrs nil, :content ("\n " {:tag :head, :attrs nil, :content ("\n " {:tag :title, :attrs nil, :content ("Test page")} "\n " {:tag :meta, :attrs {:content "Pavel Tisnovsky", :name "Author"}, :content nil} "\n " {:tag :meta, :attrs {:content "vim", :name "Generator"}, :content nil} "\n ")} "\n " {:tag :body, :attrs nil, :content ("\n " {:tag :h1, :attrs nil, :content ("Lorem Ipsum")} "\n " {:tag :div, :attrs nil, :content ("Lorem ipsum .... ............. .............")} "\n " {:tag :h1, :attrs nil, :content ("Second paragraph")} "\n " {:tag :div, :attrs nil, :content ("Vivamus fermentum.... ............. .............")} "\n " {:tag :h1, :attrs nil, :content ("Third paragraph")} "\n ")} "\n\n\n")})
Poté je použita funkce net.cgrand.enlive-html/select pro získání obsahu tagu „title“ umístěného v tagu „head“ a n-tého tagu „h1“ umístěného uvnitř tagu „body“. Výběr tagů se provádí s využitím selektorů, které mají vždy tvar vektoru (to jsme si již ostatně řekli minule). Vrácena je vždy sekvence, i když může být prázdná či může obsahovat jen jediný tag (což je první případ).
Následuje výpis zdrojového kódu demonstračního příkladu:
(ns enlive5.core (:use net.cgrand.enlive-html)) (defn load-html-page "Nacteni testovaci stranky umistene v podadresari './resources'." [] (html-resource "test.html")) (defn print-tag-content "Vypis textoveho obsahu vybraneho tagu." [tag] (println (clojure.string/join (get tag :content)))) (defn print-title "Vyber titulku stranky, tj. textu uzavreneho do <title></title>." [html-page] (print-tag-content (first (select html-page [:head :title])))) (defn print-h1 "Vyber n-teho nadpisu, kde cislovani zacina od jednicky." [html-page n] (print-tag-content (nth (select html-page [:body :h1]) (dec n)))) (defn -main "Vstupni bod do aplikace." [& args] (let [html-page (load-html-page)] (print-title html-page) (print-h1 html-page 1) (print-h1 html-page 2) (print-h1 html-page 3)))
Po spuštění tohoto příkladu by se na výstupu měly objevit tyto čtyři textové řádky:
Test page Lorem Ipsum Second paragraph Third paragraph
Vidíme, že skutečně došlo k výběru a výpisu titulku stránky i všech tří nadpisů uvedených uvnitř tagu <h1>.
5. Příklad enlive6 – threading makro jako cesta k čitelnějšímu zdrojovému kódu
Zdrojový kód předchozího demonstračního příkladu není v žádném případě dokonalý, a to mj. i z toho důvodu, že se v něm vyskytuje volání funkcí, kterým se předává výsledek jiných funkcí. Jedná se o vnořené formy, které nejsou příliš čitelné a trošku dělají Clojure (a nepřímo i LISPu) špatnou reklamu tím, že se zbytečně nadužívají kulaté závorky. Ostatně se podívejme sami na ona zmiňovaná volání:
(print-tag-content (first (select html-page [:head :title])))) (print-tag-content (nth (select html-page [:body :h1]) (dec n))))
Vylepšení zdrojového kódu je v tomto případě více než snadné, protože lze použít již v tomto seriálu několikrát zmiňované threading makro zapisované symbolem ->. Díky tomuto makru se předchozí dvě formy mohou přepsat na:
(-> html-page (select [:head :title]) first print-tag-content)) (-> html-page (select [:body :h1]) (nth (dec n)) print-tag-content))
(rozdělení na více řádků je samozřejmě nepovinné).
Funkčně identická podoba předchozího demonstračního příkladu vypadá s použitím threading makra takto:
(ns enlive6.core (:use net.cgrand.enlive-html)) (defn load-html-page "Nacteni testovaci stranky umistene v podadresari './resources'." [] (html-resource "test.html")) (defn print-tag-content "Vypis textoveho obsahu vybraneho tagu." [tag] (-> tag :content clojure.string/join println)) (defn print-title "Vyber titulku stranky, tj. textu uzavreneho do <title></title>." [html-page] (-> html-page (select [:head :title]) first print-tag-content)) (defn print-h1 "Vyber n-teho nadpisu, kde cislovani zacina od jednicky." [html-page n] (-> html-page (select [:body :h1]) (nth (dec n)) print-tag-content)) (defn -main "Vstupni bod do aplikace." [& args] (let [html-page (load-html-page)] (print-title html-page) (print-h1 html-page 1) (print-h1 html-page 2) (print-h1 html-page 3)))
6. Příklad enlive7 – příklad použití speciální formy doto
Zdrojový kód je možné vylepšit ještě dalším způsobem. Podívejme se na funkci -main:
(defn -main "Vstupni bod do aplikace." [& args] (let [html-page (load-html-page)] (print-title html-page) (print-h1 html-page 1) (print-h1 html-page 2) (print-h1 html-page 3)))
Programátora by zde mělo zaujmout především to, že hodnota navázaná na lokální symbol html-page je použita při volání dalších čtyř funkcí 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. V tomto případě je náprava snadná, protože stačí použít speciální formu doto a přepsat funkci -main následujícím způsobem:
(defn -main "Vstupni bod do aplikace." [& args] (doto (load-html-page) (print-title) (print-h1 1) (print-h1 2) (print-h1 3)))
Tato forma nejprve zavolá první funkci load-html-page a její výsledek postupně předá dalším čtyřem funkcím (jako první parametr).
Funkčně identická podoba předchozích dvou demonstračních příkladů vypadá s použitím threading makra a speciální formy doto takto:
(ns enlive7.core (:use net.cgrand.enlive-html)) (defn load-html-page "Nacteni testovaci stranky umistene v podadresari './resources'." [] (html-resource "test.html")) (defn print-tag-content "Vypis textoveho obsahu vybraneho tagu." [tag] (-> tag :content clojure.string/join println)) (defn print-title "Vyber titulku stranky, tj. textu uzavreneho do <title></title>." [html-page] (-> html-page (select [:head :title]) first print-tag-content)) (defn print-h1 "Vyber n-teho nadpisu, kde cislovani zacina od jednicky." [html-page n] (-> html-page (select [:body :h1]) (nth (dec n)) print-tag-content)) (defn -main "Vstupni bod do aplikace." [& args] (doto (load-html-page) (print-title) (print-h1 1) (print-h1 2) (print-h1 3)))
7. Další typy selektorů nabízené knihovnou Enlive
Knihovna Enlive programátorům nabízí velké množství různých selektorů, které jsou popsány na stránce http://cgrand.github.io/enlive/syntax.html. S jejich využitím je například možné nalézt ty tagy, které obsahují zadaný atribut či atributy, hledat na základě hodnot atributů atd. atd. V tabulce umístěné pod tímto odstavcem jsou některé z těchto selektorů zmíněny:
# | Funkce | Význam |
---|---|---|
1 | (attr? attribute-keyword*) | tagy obsahující zadaný atribut či atributy |
2 | (attr= (attribute-keyword value)*) | tagy obsahující atributy se specifikovanými hodnotami |
3 | (attr-has (attribute-keyword value)*) | lze zadat více hodnot atributů hledaných tagů |
4 | (attr-starts (attribute-keyword value)*) | hodnota atributu začíná na řetězec |
5 | (attr-ends (attribute-keyword value)*) | hodnota atributu končí na řetězec |
6 | (attr-contains (attribute-keyword value)*) | hodnota atributu obsahuje podřetězec |
7 | (nth-child stride? offset) | dokáže vybrat synovské pod-uzly |
8 | (nth-last-child stride? offset) | dtto, ale určení pod-uzlu probíhá opačně |
9 | node :> text-node | získání textu (content) tagu |
8. Příklad enlive8 – použití :> a (attr=) ve funkci select
V dnešním posledním demonstračním příkladu jsou použity selektory představované funkcí (attr=) a dále pak zápisem :>. První z těchto selektorů je použit pro nalezení informace o generátoru stránky:
(-> html-page (select [(attr= :name "Generator")]) first :attrs :content println))
Druhý selektor je vlastně zkratkou pro získání textu uloženého v tagu, tedy obsahu tagu:
(-> html-page (select [:div :> text-node]) first println))
Dále se vyberou všechny tagy obsahující zadaný atribut „name“:
(select html-page [(attr? :name)]
Podívejme se na celý zdrojový kód:
(ns enlive8.core (:use net.cgrand.enlive-html)) (defn load-html-page "Nacteni testovaci stranky umistene v podadresari './resources'." [] (html-resource "test.html")) (defn print-tag-content "Vypis textoveho obsahu vybraneho tagu." [tag] (-> tag :content clojure.string/join println)) (defn print-title "Vyber titulku stranky, tj. textu uzavreneho do <title></title>." [html-page] (-> html-page (select [:head :title]) first print-tag-content)) (defn print-h1 "Vyber n-teho nadpisu, kde cislovani zacina od jednicky." [html-page n] (-> html-page (select [:body :h1]) (nth (dec n)) print-tag-content)) (defn print-first-paragraph "Vyber *obsahu* prvniho odstavce." [html-page] (-> html-page (select [:div :> text-node]) first println)) (defn print-generator "Vyber a vypis generatoru nacteneho z metainformaci." [html-page] (-> html-page (select [(attr= :name "Generator")]) first :attrs :content println)) (defn print-meta-tag [tag] (let [attrs (:attrs tag)] (println (:name attrs) " -> " (:content attrs)))) (defn print-all-metatags "Vyber a vypis vsech metainformaci." [html-page] (doseq [tag (select html-page [(attr? :name)])] (print-meta-tag tag))) (defn -main "Vstupni bod do aplikace." [& args] (doto (load-html-page) (print-title) (print-h1 1) (print-h1 2) (print-h1 3) (print-first-paragraph) (print-generator) (print-all-metatags)))
Po spuštění tohoto příkladu by se na standardním výstupu měl objevit text:
Test page Lorem Ipsum Second paragraph Third paragraph Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est. vim Author -> Pavel Tisnovsky Generator -> vim
9. Repositář s dnešními demonstračními příklady
Všech pět dnes zmíněných demonstračních příkladů bylo, podobně jako v předchozích částech tohoto seriálu, uloženo do Git repositáře dostupného na adrese https://github.com/tisnik/clojure-examples. V tabulce zobrazené pod tímto odstavcem naleznete na zdrojové kódy jednotlivých demonstračních příkladů přímé odkazy:
Příklady z předchozího týdne (jen pro úplnost):
# | Příklad | Github |
---|---|---|
1 | enlive1 | https://github.com/tisnik/clojure-examples/tree/master/enlive1 |
2 | enlive2 | https://github.com/tisnik/clojure-examples/tree/master/enlive2 |
3 | enlive3 | https://github.com/tisnik/clojure-examples/tree/master/enlive3 |
10. Odkazy na předchozí části tohoto seriálu
- Leiningen: nástroj pro správu projektů napsaných v Clojure
http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure/ - 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/ - 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/ - 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/ - 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/ - 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/ - Programovací jazyk Clojure a databáze (1.část)
http://www.root.cz/clanky/programovaci-jazyk-clojure-a-databaze-1-cast/ - Pluginy pro Leiningen
http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-pluginy-pro-leiningen/ - 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/ - 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/ - 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/ - 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/ - 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/ - Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure
http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure/ - 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/ - 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/ - Programovací jazyk Clojure a práce s Gitem
http://www.root.cz/clanky/programovaci-jazyk-clojure-a-prace-s-gitem/ - Programovací jazyk Clojure a práce s Gitem (2)
http://www.root.cz/clanky/programovaci-jazyk-clojure-a-prace-s-gitem-2/ - Programovací jazyk Clojure – triky při práci s řetězci
http://www.root.cz/clanky/programovaci-jazyk-clojure-triky-pri-praci-s-retezci/ - Programovací jazyk Clojure – triky při práci s kolekcemi
http://www.root.cz/clanky/programovaci-jazyk-clojure-triky-pri-praci-s-kolekcemi/ - Programovací jazyk Clojure – práce s mapami a množinami
http://www.root.cz/clanky/programovaci-jazyk-clojure-prace-s-mapami-a-mnozinami/ - Programovací jazyk Clojure – základy zpracování XML
http://www.root.cz/clanky/programovaci-jazyk-clojure-zaklady-zpracovani-xml/ - Programovací jazyk Clojure – testování s využitím knihovny Expectations
http://www.root.cz/clanky/programovaci-jazyk-clojure-testovani-s-vyuzitim-knihovny-expectations/ - 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/ - Enlive – výkonný šablonovací systém pro jazyk Clojure
http://www.root.cz/clanky/enlive-vykonny-sablonovaci-system-pro-jazyk-clojure/
11. Odkazy na Internetu
- Syntax pro selektory
http://cgrand.github.io/enlive/syntax.html - Clojure Cookbook: Templating HTML with Enlive
https://github.com/clojure-cookbook/clojure-cookbook/blob/master/07_webapps/7–11_enlive.asciidoc - An Introduction to Enlive
https://github.com/swannodette/enlive-tutorial/ - Enlive na GitHubu
https://github.com/cgrand/enlive - Expectations: příklady atd.
http://jayfields.com/expectations/ - Expectations na GitHubu
https://github.com/jaycfields/expectations - Lein-expectations na GitHubu
https://github.com/gar3thjon3s/lein-expectations - Testing Clojure With Expectations
https://semaphoreci.com/blog/2014/09/23/testing-clojure-with-expectations.html - Clojure testing TDD/BDD libraries: clojure.test vs Midje vs Expectations vs Speclj
https://www.reddit.com/r/Clojure/comments/1viilt/clojure_testing_tddbdd_libraries_clojuretest_vs/ - Testing: One assertion per test
http://blog.jayfields.com/2007/06/testing-one-assertion-per-test.html - Rewriting Your Test Suite in Clojure in 24 hours
http://blog.circleci.com/rewriting-your-test-suite-in-clojure-in-24-hours/ - Clojure doc: zipper
http://clojuredocs.org/clojure.zip/zipper - Clojure doc: parse
http://clojuredocs.org/clojure.xml/parse - Clojure doc: xml-zip
http://clojuredocs.org/clojure.zip/xml-zip - Clojure doc: xml-seq
http://clojuredocs.org/clojure.core/xml-seq - Parsing XML in Clojure
https://github.com/clojuredocs/guides - Clojure Zipper Over Nested Vector
https://vitalyper.wordpress.com/2010/11/23/clojure-zipper-over-nested-vector/ - Understanding Clojure's PersistentVector implementation
http://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation - Understanding Clojure's PersistentHashMap (deftwice…)
http://blog.higher-order.net/2009/09/08/understanding-clojures-persistenthashmap-deftwice.html - Assoc and Clojure's PersistentHashMap: part ii
http://blog.higher-order.net/2010/08/16/assoc-and-clojures-persistenthashmap-part-ii.html - Ideal Hashtrees (paper)
http://lampwww.epfl.ch/papers/idealhashtrees.pdf - Clojure home page
http://clojure.org/ - Clojure (downloads)
http://clojure.org/downloads - Clojure Sequences
http://clojure.org/sequences - Clojure Data Structures
http://clojure.org/data_structures - 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 - 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 - Clojure – Functional Programming for the JVM
http://java.ociweb.com/mark/clojure/article.html - Clojure quick reference
http://faustus.webatu.com/clj-quick-ref.html - 4Clojure
http://www.4clojure.com/ - ClojureDoc (rozcestník s dokumentací jazyka Clojure)
http://clojuredocs.org/ - Clojure (na Wikipedia EN)
http://en.wikipedia.org/wiki/Clojure - Clojure (na Wikipedia CS)
http://cs.wikipedia.org/wiki/Clojure - SICP (The Structure and Interpretation of Computer Programs)
http://mitpress.mit.edu/sicp/ - Pure function
http://en.wikipedia.org/wiki/Pure_function - Funkcionální programování
http://cs.wikipedia.org/wiki/Funkcionální_programování - Čistě funkcionální (datové struktury, jazyky, programování)
http://cs.wikipedia.org/wiki/Čistě_funkcionální - 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 - Clojure Macro Tutorial (Part II: The Compiler Strikes Back)
http://www.learningclojure.com/2010/09/clojure-macro-tutorial-part-ii-compiler.html - Clojure Macro Tutorial (Part III: Syntax Quote)
http://www.learningclojure.com/2010/09/clojure-macro-tutorial-part-ii-syntax.html - Tech behind Tech: Clojure Macros Simplified
http://techbehindtech.com/2010/09/28/clojure-macros-simplified/ - Fatvat – Exploring functional programming: Clojure Macros
http://www.fatvat.co.uk/2009/02/clojure-macros.html - Eulerovo číslo
http://cs.wikipedia.org/wiki/Eulerovo_číslo - List comprehension
http://en.wikipedia.org/wiki/List_comprehension - List Comprehensions in Clojure
http://asymmetrical-view.com/2008/11/18/list-comprehensions-in-clojure.html - Clojure Programming Concepts: List Comprehension
http://en.wikibooks.org/wiki/Clojure_Programming/Concepts#List_Comprehension - Clojure core API: for macro
http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/for - cirrus machina – The Clojure for macro
http://www.cirrusmachina.com/blog/comment/the-clojure-for-macro/ - Riastradh's Lisp Style Rules
http://mumble.net/~campbell/scheme/style.txt - Dynamic Languages Strike Back
http://steve-yegge.blogspot.cz/2008/05/dynamic-languages-strike-back.html - Scripting: Higher Level Programming for the 21st Century
http://www.tcl.tk/doc/scripting.html - Java Virtual Machine Support for Non-Java Languages
http://docs.oracle.com/javase/7/docs/technotes/guides/vm/multiple-language-support.html - Třída java.lang.String
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html - Třída java.lang.StringBuffer
http://docs.oracle.com/javase/7/docs/api/java/lang/StringBuffer.html - Třída java.lang.StringBuilder
http://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html - StringBuffer versus String
http://www.javaworld.com/article/2076072/build-ci-sdlc/stringbuffer-versus-string.html - Threading macro (dokumentace k jazyku Clojure)
https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/-> - Understanding the Clojure → macro
http://blog.fogus.me/2009/09/04/understanding-the-clojure-macro/ - clojure.inspector
http://clojure.github.io/clojure/clojure.inspector-api.html - The Clojure Toolbox
http://www.clojure-toolbox.com/ - Unit Testing in Clojure
http://nakkaya.com/2009/11/18/unit-testing-in-clojure/ - Testing in Clojure (Part-1: Unit testing)
http://blog.knoldus.com/2014/03/22/testing-in-clojure-part-1-unit-testing/ - API for clojure.test – Clojure v1.6 (stable)
https://clojure.github.io/clojure/clojure.test-api.html - Leiningen: úvodní stránka
http://leiningen.org/ - Leiningen: Git repository
https://github.com/technomancy/leiningen - leiningen-win-installer
http://leiningen-win-installer.djpowell.net/ - Clojure 1: Úvod
http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm/ - Clojure 2: Symboly, kolekce atd.
http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-2-cast/ - 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/ - 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/ - 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/ - Clojure 6: Podpora pro paralelní programování
http://www.root.cz/clanky/programovaci-jazyk-clojure-6-futures-nejsou-jen-financni-derivaty/ - Clojure 7: Další funkce pro paralelní programování
http://www.root.cz/clanky/programovaci-jazyk-clojure-7-dalsi-podpurne-prostredky-pro-paralelni-programovani/ - 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/ - 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/ - Clojure 10: Kooperace mezi Clojure a Javou
http://www.root.cz/clanky/programovaci-jazyk-clojure-10-kooperace-mezi-clojure-a-javou-pokracovani/ - Clojure 11: Generátorová notace seznamu/list comprehension
http://www.root.cz/clanky/programovaci-jazyk-clojure-11-generatorova-notace-seznamu-list-comprehension/ - 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/ - 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/ - Clojure 14: Základy práce se systémem maker
http://www.root.cz/clanky/programovaci-jazyk-clojure-14-zaklady-prace-se-systemem-maker/ - Clojure 15: Tvorba uživatelských maker
http://www.root.cz/clanky/programovaci-jazyk-clojure-15-tvorba-uzivatelskych-maker/ - Clojure 16: Složitější uživatelská makra
http://www.root.cz/clanky/programovaci-jazyk-clojure-16-slozitejsi-uzivatelska-makra/ - Clojure 17: Využití standardních maker v praxi
http://www.root.cz/clanky/programovaci-jazyk-clojure-17-vyuziti-standardnich-maker-v-praxi/ - Clojure 18: Základní techniky optimalizace aplikací
http://www.root.cz/clanky/programovaci-jazyk-clojure-18-zakladni-techniky-optimalizace-aplikaci/ - Clojure 19: Vývojová prostředí pro Clojure
http://www.root.cz/clanky/programovaci-jazyk-clojure-19-vyvojova-prostredi-pro-clojure/ - 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/ - Clojure 21: ClojureScript aneb překlad Clojure do JS
http://www.root.cz/clanky/programovaci-jazyk-clojure-21-clojurescript-aneb-preklad-clojure-do-javascriptu/ - Clojure.org: Vars and the Global Environment
http://clojure.org/Vars - Clojure.org: Refs and Transactions
http://clojure.org/Refs - Clojure.org: Atoms
http://clojure.org/Atoms - Clojure.org: Agents as Asynchronous Actions
http://clojure.org/agents - Transient Data Structureshttp://clojure.org/transients