Hlavní navigace

Základní knihovny pro 2D grafiku v jazyku Racket

Pavel Tišnovský

V dnešním článku o jazyku Racket si ukážeme vybrané balíčky sloužící pro práci s grafikou. Popis začneme u balíčku určeného pro vykreslování 2D grafiky, ovšem nezapomeneme ani na (kdysi velmi populární) balíček s želví grafikou.

Doba čtení: 39 minut

Sdílet

11. Vykreslení loga programovacího jazyka Racket

12. Spline křivka

13. Nastavení alfa kanálu (průhlednosti)

14. Vykreslení textu

15. Želví grafika

16. Použití funkce repeat pro vykreslení složitějších obrazců

17. Další možnosti želví grafiky

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

19. Literatura

20. Odkazy na Internetu

1. Základní knihovny pro 2D grafiku v jazyku Racket

Na rozdíl od předchozích tří článků [1] [2] [3], v nichž jsme se věnovali základním konceptům, na nichž je postaven programovací jazyk Racket, se dnes začneme věnovat praktičtějším příkladům, které se mj. používají i ve výuce (i když je nutné na tomto místě poznamenat, že se Racket do výuky nerozšířil do takové míry, jak jeho tvůrci doufali). Mezi nejvíce názorné metody výuky programování stále patří použití jednoduché 2D grafiky a pro tento účel v Racketu nalezneme hned několik knihoven, zejména pak knihovnu Racket Drawing Toolkit představovanou balíčkem racket/draw.

V první části dnešního článku se budeme zabývat výše zmíněným balíčkem racket/draw, v níž nalezneme většinu standardních funkcí pro vykreslování 2D grafiky. V části druhé si pak ve stručnosti popíšeme knihovnu graphics/turtles, v níž je implementována takzvaná želví grafika neboli turtle graphics.

Balíček racket/draw je určen pro vykreslování 2D grafiky tvořené jak základními geometrickými tvary (úsečka, oblouk, elipsa), tak i textem a popř. i cestami (paths). Většina konceptů, na nichž je tato knihovna postavena, bude mnoha čtenářům připadat známá. Není to samozřejmě náhodou, protože se tvůrci inspirovali PostScriptem [4], z něhož je nepřímo odvozen i jazyk SVG [5]. To mj. znamená, že se setkáme s takovými termíny, jako je pero (pen), štětec (brush), cesta (path) atd. Vzhledem k tomu, že jsou tyto pojmy vysvětleny v odkazovaných článcích, budeme se dnes soustředit především na způsob jejich použití v programovacím jazyku Racket.

2. Bitmapy, grafické kontexty a vykreslení (rasterizace) úseček

Knihovna používá koncepty objektově orientovaného programování, s nimiž jsme se v jazyku Racket prozatím nesetkali, ovšem dnes nám bude stačit pouze vědět, jakým způsobem se vytvoří (zkonstruuje) objekt a jak se tomuto objektu pošle zpráva, resp. (pokud preferujete terminologii C++ či Javy) jak se zavolá metoda objektu. Nový objekt se zkonstruuje pomocí formy new, které se předá výraz typu třída a případné parametry konstruktoru:

(new bitmap-dc% [bitmap target])
Poznámka: většinou jména tříd končí znakem procenta, všechny třídy jsou pak odvozeny od supertřídy object%.

Jakmile je objekt zkonstruován, je možné mu poslat zprávou pomocí metody send popř. nějaké další varianty této formy (variant existuje několik, velmi užitečná je forma send*, která objektu postupně pošle více zpráv):

(send objekt metoda argumenty metody)
 
(send* objekt zpráva1 zpráva2 zpráva3 ...)

Znalost těchto dvou forem nám bude pro účely dnešního článku plně dostačovat.

Nyní si ukažme ten nejjednodušší demonstrační příklad, na němž budou vysvětleny dva základní koncepty knihovny racket/draw:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define target (make-bitmap 256 256))
(define dc (new bitmap-dc% [bitmap target]))
 
(send dc draw-line 0 0 255 255)
(send dc draw-line 0 255 255 0)
 
(send target save-file "01.png" 'png)

Obrázek 1: Výsledek běhu dnešního prvního demonstračního příkladu.

V tomto příkladu se postupně vykonají následující operace:

  1. Vytvoří se bitmapa (rastrový obrázek), do kterého se bude provádět vykreslování. Povšimněte si, že u bitmapy musíme specifikovat její horizontální i vertikální rozlišení a popř. i další parametry (například to, zda se má používat alfa kanál atd.).
  2. Vytvoří a inicializuje se takzvaný grafický kontext držící stav vykreslovacího enginu (šířku a barvu pera atd.). U samotných vykreslovacích operací se pouze specifikuje, jaký tvar se má vykreslit a jaký je jeho geometrický tvar (souřadnice). Barva vykreslení či výplně je součástí grafického kontextu.
  3. Následně přes grafický kontext vykreslíme základní geometrický tvar – úsečku. Souřadnice koncových bodů úsečky jsou specifikovány v souřadném systému bitmapy, v našem případě v souřadném systému, v němž má x-ová i y-ová osa limity 0 až 255 (ve skutečnosti to není zcela pravda, protože je možné provádět lineární transformace souřadnic, ty však prozatím nemáme nastavené).
  4. Nakonec je bitmapa uložena do rastrového souboru ve formátu PNG, ovšem v případě potřeby je možné zvolit i další formáty, pochopitelně včetně JPEGu.

Ve druhém příkladu navíc bitmapu nejprve „smažeme“ nakreslením bílého obdélníku (viz zvýrazněná část skriptu):

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define target (make-bitmap 256 256))
(define dc (new bitmap-dc% [bitmap target]))
 
(send dc draw-rectangle 0 0 256 256)
 
(send dc draw-line 0 0 255 255)
(send dc draw-line 0 255 255 0)
 
(send target save-file "02.png" 'png)

Obrázek 2: Výsledek běhu příkladu druhého.

3. Nastavení vizuálních vlastností vykreslovaných objektů

Podobně, jako je tomu například ve vektorovém formátu SVG, PostScriptu či v knihovně OpenVG, se i při použití knihovny racket/draw setkáme se třemi důležitými pojmy:

  1. Pero (pen) je nástroj použitý při vykreslování obrysu tvarů a samozřejmě i všech liniových tvarů (úsečky, oblouky, …).
  2. Štětec (brush) je nástroj použitý pro vyplnění uzavřených tvarů (obdélník, polygon, elipsa, cesta).
  3. Cesta (path) se používá k popisu složitějších tvarů složených z úseček a oblouků. Nad cestami je definováno větší množství operací, například test, zda bod leží uvnitř objektu popsaného cestou atd.
Poznámka: styly vykreslování se nastavují pro všechny běžné geometrické tvary stejnými metodami. Výjimkou jsou texty (font) s vlastním nastavením nezávislým na ostatních grafických entitách.

Barva obrysů lze nastavit takto:

(send dc set-pen "red" 3 'solid)

4. Vykreslení vyplněných 2D objektů

Některé objekty jsou „otevřené“ (úsečka, oblouk, spline křivka), další „uzavřené“ (obdélník, elipsa). U uzavřených objektů je možné zvolit, jakým způsobem se vyplní jejich vnitřek. V nejjednodušším případě se vyplnění provede konstantní barvou, což si ukážeme v dalším příkladu. Barva výplně je součástí stavu takzvaného „štětce“ (brush) a nastavuje se metodou set-brush:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define target (make-bitmap 256 256))
(define dc (new bitmap-dc% [bitmap target]))
 
(send dc set-brush "white" 'solid)
 
(send dc set-pen "white" 1 'transparent)
(send dc draw-rectangle 0 0 256 256)
 
(send dc set-pen "red" 3 'solid)
(send dc draw-line 0 0 255 255)
(send dc draw-line 0 255 255 0)
 
(send target save-file "03.png" 'png)

Obrázek 3: Třetí demonstrační příklad s vykresleným obdélníkem a dvojicí úseček.

5. Nastavení antialiasingu při vykreslování

Nejrychlejším algoritmem pro vykreslování úseček do bitmapy je slavný Bresenhamův algoritmus. Ovšem klasická podoba tohoto algoritmu má jednu podstatnou nevýhodu, která je navíc ještě zviditelněna kvalitními monitory s pevným rastrem – stopa úsečky tvoří typické „schody“, takže se výsledek někdy označuje „jagged lines“. Existují ovšem i vykreslovací algoritmy, které dokážou úsečky a další tvary vykreslit s využitím antialiasingu. I tyto algoritmy jsou v knihovně racket/draw podporovány a to dokonce ve dvou variantách. První varianta počítá s tím že koncové body úseček a dalších tvarů leží ve středech pixelů, druhá varianta naopak počítá s tím, že koncové body leží na hranicích mezi pixely. Rozdíly mezi všemi třemi vykreslovacími algoritmy jsou ukázány na trojici demonstračních příkladů.

Vykreslení úseček klasickým Bresenhamovým algoritmem se „schody“:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define target (make-bitmap 256 256))
(define dc (new bitmap-dc% [bitmap target]))
 
(send dc set-brush "white" 'solid)
 
(send dc set-pen "white" 1 'transparent)
(send dc draw-rectangle 0 0 256 256)
 
(send dc set-pen "black" 1 'solid)
 
(for ([i (in-range 0 256 10)])
     (send dc draw-line 255 0 i i)
     (send dc draw-line 0 i i 255))
 
(send target save-file "04.png" 'png)

Obrázek 4: Vykreslení úseček klasickým Bresenhamovým algoritmem se „schody“.

První algoritmus využívající antialiasing. Zpráva/metoda, která tento algoritmus zapíná, je zvýrazněna tučným písmem:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define target (make-bitmap 256 256))
(define dc (new bitmap-dc% [bitmap target]))
 
(send dc set-brush "white" 'solid)
 
(send dc set-pen "white" 1 'transparent)
(send dc draw-rectangle 0 0 256 256)
 
(send dc set-pen "black" 1 'solid)
(send dc set-smoothing 'smoothed)
 
(for ([i (in-range 0 256 10)])
     (send dc draw-line 255 0 i i)
     (send dc draw-line 0 i i 255))
 
(send target save-file "05.png" 'png)

Obrázek 5: První algoritmus pro antialiasing.

Druhý algoritmus využívající antialiasing. Zpráva/metoda, která tento algoritmus zapíná, je opět zvýrazněna:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define target (make-bitmap 256 256))
(define dc (new bitmap-dc% [bitmap target]))
 
(send dc set-brush "white" 'solid)
 
(send dc set-pen "white" 1 'transparent)
(send dc draw-rectangle 0 0 256 256)
 
(send dc set-pen "black" 1 'solid)
(send dc set-smoothing 'aligned)
 
(for ([i (in-range 0 256 10)])
     (send dc draw-line 255 0 i i)
     (send dc draw-line 0 i i 255))
 
(send target save-file "06.png" 'png)

Obrázek 6: Druhý algoritmus pro antialiasing.

Rozdíl mezi oběma algoritmy používajícími antialiasing je ještě více viditelný v případě, že budeme vykreslovat vodorovné či naopak svislé úsečky. Ukažme si rozdíl na příkladu s vodorovnými úsečkami.

První algoritmus využívající antialiasing. Zpráva/metoda, která tento algoritmus zapíná, je zvýrazněna tučným písmem:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define target (make-bitmap 256 256))
(define dc (new bitmap-dc% [bitmap target]))
 
(send dc set-brush "white" 'solid)
 
(send dc set-pen "white" 1 'transparent)
(send dc draw-rectangle 0 0 256 256)
 
(send dc set-pen "black" 1 'solid)
(send dc set-smoothing 'smoothed)
 
(for ([i (in-range 0 256 10)])
     (send dc draw-line 0 i 255 i))
 
(send target save-file "07.png" 'png)

Obrázek 7: První algoritmus využívající antialiasing pro vykreslení vodorovných úseček.

Druhý algoritmus využívající antialiasing. Zpráva/metoda, která tento algoritmus zapíná, je opět zvýrazněna:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define target (make-bitmap 256 256))
(define dc (new bitmap-dc% [bitmap target]))
 
(send dc set-brush "white" 'solid)
 
(send dc set-pen "white" 1 'transparent)
(send dc draw-rectangle 0 0 256 256)
 
(send dc set-pen "black" 1 'solid)
(send dc set-smoothing 'aligned)
 
(for ([i (in-range 0 256 10)])
     (send dc draw-line 0 i 255 i))
 
(send target save-file "08.png" 'png)

Obrázek 8: Druhý algoritmus využívající antialiasing pro vykreslení vodorovných úseček.

6. Styl vykreslovaných úseček, oblouků, křivek a cest

Při kresbě liniových obrazců nebo okrajů plošných obrazců je možné zvolit vzorek (styl) úseček – plná (výchozí nastavení), čárkovaná, čerchovaná, střídavá apod. Tento styl se nastavuje posledním parametrem metody set-pen a jednotlivé možnosti jsou ukázány v dalším demonstračním příkladu (pro větší kvalitu výsledku je povolen antialiasing):

Obrázek 9: Několik úseček s různým stylem vykreslování.

Poznámka: povšimněte si, že se vzorek zvětšuje společně s nastavenou šířkou vykreslované úsečky (což v jiných knihovnách podobného zaměření obecně neplatí).

Úplný zdrojový kód tohoto demonstračního příkladu vypadá následovně:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define target (make-bitmap 256 256))
(define dc (new bitmap-dc% [bitmap target]))
 
(send dc set-brush "white" 'solid)
 
(send dc set-pen "white" 1 'transparent)
(send dc draw-rectangle 0 0 256 256)
 
(send dc set-smoothing 'aligned)
 
(send dc set-pen "black" 1 'solid)
(send dc draw-line 0 10 255 10)
 
(send dc set-pen "black" 1 'dot)
(send dc draw-line 0 20 255 20)
 
(send dc set-pen "black" 1 'long-dash)
(send dc draw-line 0 30 255 30)
 
(send dc set-pen "black" 1 'short-dash)
(send dc draw-line 0 40 255 40)
 
(send dc set-pen "black" 1 'dot-dash)
(send dc draw-line 0 50 255 50)
 
(send dc set-pen "gray" 5 'solid)
(send dc draw-line 0 80 255 80)
 
(send dc set-pen "gray" 5 'dot)
(send dc draw-line 0 90 255 90)
 
(send dc set-pen "gray" 5 'long-dash)
(send dc draw-line 0 100 255 100)
 
(send dc set-pen "gray" 5 'short-dash)
(send dc draw-line 0 110 255 110)
 
(send dc set-pen "gray" 5 'dot-dash)
(send dc draw-line 0 120 255 120)
 
(send dc set-pen "darkgreen" 15 'solid)
(send dc draw-line 0 150 255 150)
 
(send dc set-pen "darkgreen" 15 'dot)
(send dc draw-line 0 170 255 170)
 
(send dc set-pen "darkgreen" 15 'long-dash)
(send dc draw-line 0 190 255 190)
 
(send dc set-pen "darkgreen" 15 'short-dash)
(send dc draw-line 0 210 255 210)
 
(send dc set-pen "darkgreen" 15 'dot-dash)
(send dc draw-line 0 230 255 230)
 
 
(send target save-file "09.png" 'png)

7. Změna tvaru stopy na konci úseček

Konce (zejména) širokých úseček či oblouků mohou být zaobleny, popř. mohou končit přímo na zadaném koncovém bodě (vrcholu) nebo může křivka přesahovat koncový bod tak, aby vzdálenost koncového bodu (vrchol) od vykresleného konce křivky odpovídala polovině jejího průměru. Toto chování vykreslovacího algoritmu nelze nastavit přímo metodou set-pen, ale musíme použít tento postup:

(send dc set-pen (send the-pen-list find-or-create-pen "black" 1 'solid 'butt))

Alternativně můžeme použít metodu set-cap.

Důležitý je poslední parametr metody find-or-create-pen, který může nabývat hodnot:

  1. 'round (zakulacený konec křivky)
  2. 'projecting (kolmé ukončení křivky, křivka je prodloužena přes koncový bod)
  3. 'butt (kolmé ukončení křivky, křivka končí přímo v koncovém bodě)

Podívejme se nyní na úpravu předchozího příkladu tak, aby se změnil způsob vykreslení konců úseček:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define target (make-bitmap 256 256))
(define dc (new bitmap-dc% [bitmap target]))
 
(send dc set-brush "white" 'solid)
 
(send dc set-pen "white" 1 'transparent)
(send dc draw-rectangle 0 0 256 256)
 
(send dc set-smoothing 'aligned)
 
(send dc set-pen (send the-pen-list find-or-create-pen "black" 1 'solid 'butt))
(send dc draw-line 0 10 255 10)
 
(send dc set-pen (send the-pen-list find-or-create-pen "black" 1 'dot 'butt))
(send dc draw-line 0 20 255 20)
 
(send dc set-pen (send the-pen-list find-or-create-pen "black" 1 'long-dash 'butt))
(send dc draw-line 0 30 255 30)
 
(send dc set-pen (send the-pen-list find-or-create-pen "black" 1 'short-dash 'butt))
(send dc draw-line 0 40 255 40)
 
(send dc set-pen (send the-pen-list find-or-create-pen "black" 1 'dot-dash 'butt))
(send dc draw-line 0 50 255 50)
 
(send dc set-pen (send the-pen-list find-or-create-pen "gray" 5 'solid 'butt))
(send dc draw-line 0 80 255 80)
 
(send dc set-pen (send the-pen-list find-or-create-pen "gray" 5 'dot 'butt))
(send dc draw-line 0 90 255 90)
 
(send dc set-pen (send the-pen-list find-or-create-pen "gray" 5 'long-dash 'butt))
(send dc draw-line 0 100 255 100)
 
(send dc set-pen (send the-pen-list find-or-create-pen "gray" 5 'short-dash 'butt))
(send dc draw-line 0 110 255 110)
 
(send dc set-pen (send the-pen-list find-or-create-pen "gray" 5 'dot-dash 'butt))
(send dc draw-line 0 120 255 120)
 
(send dc set-pen (send the-pen-list find-or-create-pen "darkgreen" 15 'solid 'butt))
(send dc draw-line 0 150 255 150)
 
(send dc set-pen (send the-pen-list find-or-create-pen "darkgreen" 15 'dot 'butt))
(send dc draw-line 0 170 255 170)
 
(send dc set-pen (send the-pen-list find-or-create-pen "darkgreen" 15 'long-dash 'butt))
(send dc draw-line 0 190 255 190)
 
(send dc set-pen (send the-pen-list find-or-create-pen "darkgreen" 15 'short-dash 'butt))
(send dc draw-line 0 210 255 210)
 
(send dc set-pen (send the-pen-list find-or-create-pen "darkgreen" 15 'dot-dash 'butt))
(send dc draw-line 0 230 255 230)
 
 
(send target save-file "10.png" 'png)

Obrázek 10: Změněné konce úseček.

8. Styl výplně uzavřených objektů

Uzavřené dvourozměrné entity, mezi něž náleží především obdélníky a elipsy (speciálně pak kružnice) mohou být vyplněny, což jsme si již ostatně ukázali ve druhém demonstračním příkladu. Tradičně se může jednat o výplň konstantní barvou, výplň vzorkem (hatch), bitmapou nebo gradientním barvovým přechodem. Nejdříve si ukážeme vyplnění obdélníků vzorkem. V knihovně racket/draw je předpřipraveno několik vzorků, které jsou všechny použity v dalším demonstračním příkladu. Jejich názvy jsou ve zdrojovém kódu tohoto příkladu zvýrazněny tučným písmem:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define target (make-bitmap 256 256))
(define dc (new bitmap-dc% [bitmap target]))
 
(send dc set-brush "white" 'solid)
(send dc set-pen "white" 1 'transparent)
(send dc draw-rectangle 0 0 256 256)
 
(send dc set-brush "black" 'transparent)
(send dc draw-rectangle 10 10 50 50)
 
(send dc set-brush "black" 'solid)
(send dc draw-rectangle 105 10 50 50)
 
(send dc set-brush "black" 'hilite)
(send dc draw-rectangle 200 10 50 50)
 
 
(send dc set-brush "black" 'horizontal-hatch)
(send dc draw-rectangle 10 105 50 50)
 
(send dc set-brush "black" 'vertical-hatch)
(send dc draw-rectangle 105 105 50 50)
 
(send dc set-brush "black" 'cross-hatch)
(send dc draw-rectangle 200 105 50 50)
 
 
(send dc set-brush "black" 'bdiagonal-hatch)
(send dc draw-rectangle 10 200 50 50)
 
(send dc set-brush "black" 'fdiagonal-hatch)
(send dc draw-rectangle 105 200 50 50)
 
(send dc set-brush "black" 'crossdiag-hatch)
(send dc draw-rectangle 200 200 50 50)
 
 
(send target save-file "11.png" 'png)

Výsledek vypadá následovně:

Obrázek 11: Devět čtverců, každý vykreslený s jiným stylem výplně. První čtverec je vykreslen s transparentní výplní a není viditelný, protože i jeho okraj je transparentní.

9. Gradientní barvové přechody

Další demonstrační příklad je poněkud složitější, protože je v něm deklarován a následně použit gradientní barvový přechod, který posloužil jako výplň uzavřeného 2D obrazce, zde konkrétně obdélníku. Povšimněte si, jakým způsobem je gradientní přechod deklarován – zvolí se dva body v ploše a nakonec barvy ležící na spojnici mezi těmito dvěma body. Barev lze zadat libovolné množství, jen je zapotřebí udržovat seznam setříděný podle parametru t rostoucího od 0 do 1:

(new linear-gradient%
     [x0 0]
     [y0 100]
     [x1 100]
     [y1 0]
     [stops
      (list (list 0   (make-object color% 255 0 0))
            (list 0.5 (make-object color% 0 255 0))
            (list 1   (make-object color% 0 0 255)))])]))

Jeho následné nastavení a použití je zcela jednoduché:

(define rectangle-brush
  (new brush% [gradient ...]))
 
(send dc set-brush rectangle-brush)

S výsledkem:

Obrázek 12: Obdélník vyplněný s využití barvového gradientního přechodu.

Následuje výpis úplného zdrojového kódu tohoto demonstračního příkladu:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define target (make-bitmap 256 256))
(define dc (new bitmap-dc% [bitmap target]))
 
(send dc set-brush "white" 'solid)
(send dc set-pen "white" 1 'transparent)
(send dc draw-rectangle 0 0 256 256)
 
(define rectangle-brush
  (new brush%
       [gradient
        (new linear-gradient%
             [x0 0]
             [y0 100]
             [x1 100]
             [y1 0]
             [stops
              (list (list 0   (make-object color% 255 0 0))
                    (list 0.5 (make-object color% 0 255 0))
                    (list 1   (make-object color% 0 0 255)))])]))
 
(send dc set-brush rectangle-brush)
(send dc draw-rectangle 0 0 255 255)
 
(send target save-file "12.png" 'png)

10. Cesty

Dalším důležitým konceptem, s nímž se setkáme jak v knihovně , tak i ve výše zmíněném PostScriptu či SVG, jsou takzvané cesty. Jedná se o geometrické tvary vytvořené z úseček, oblouků a křivek. Cesty mohou být uzavřené (potom je lze vyplnit) či otevřené. Samotná cesta je realizována objektem typu dc-path%:

(new dc-path%)

Tomuto objektu se potom posílají zprávy pro přidání nového úsečkového segmentu (line-to), křivkového segmentu (curve-to) či o posunu aktivního bodu na zadané souřadnice (move-to):

(let ([p (new dc-path%)])
    (send p move-to 153 44)
    (send p line-to 161.5 60)
    (send p curve-to 202.5 49 230 42 245 61)
    ...
    ...
    ...

Podívejme se nyní na příklad, který po svém spuštění vykreslí část loga programovacího jazyka Racket:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define target (make-bitmap 256 256))
(define dc (new bitmap-dc% [bitmap target]))
 
(send dc set-brush "white" 'solid)
(send dc set-pen "white" 1 'transparent)
(send dc draw-rectangle 0 0 256 256)
 
(define left-lambda-path
  (let ([p (new dc-path%)])
    (send p move-to 153 44)
    (send p line-to 161.5 60)
    (send p curve-to 202.5 49 230 42 245 61)
    (send p curve-to 280.06 105.41 287.5 141 296.5 186)
    (send p curve-to 301.12 209.08 299.11 223.38 293.96 244)
    (send p curve-to 281.34 294.54 259.18 331.61 233.5 375)
    (send p curve-to 198.21 434.63 164.68 505.6 125.5 564)
    (send p line-to 135 572)
    p))
 
(send dc translate 5 5)
(send dc scale 0.4 0.4)
 
(send dc set-smoothing 'smoothed)
(send dc set-pen "black" 1 'solid)
(send dc draw-path left-lambda-path)
 
(send target save-file "13.png" 'png)

Obrázek 13: Cesta vykreslená předchozím demonstračním příkladem.

11. Vykreslení loga programovacího jazyka Racket

Následující demonstrační příklad byl převzat přímo z dokumentace programovacího jazyka Racket, ovšem byl pro účely dnešního článku zjednodušen. Tento příklad slouží pro vykreslení několika cest, po jejichž vyplnění vznikne logo tohoto programovacího jazyka:

Obrázek 14: Logo programovacího jazyka Racket vykresleného dále vypsaným příkladem.

Úplný zdrojový kód tohoto příkladu vypadá následovně:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define target (make-bitmap 256 256))
(define dc (new bitmap-dc% [bitmap target]))
 
(send dc set-brush "white" 'solid)
(send dc set-pen "white" 1 'transparent)
(send dc draw-rectangle 0 0 256 256)
 
(define left-lambda-path
  (let ([p (new dc-path%)])
    (send p move-to 153 44)
    (send p line-to 161.5 60)
    (send p curve-to 202.5 49 230 42 245 61)
    (send p curve-to 280.06 105.41 287.5 141 296.5 186)
    (send p curve-to 301.12 209.08 299.11 223.38 293.96 244)
    (send p curve-to 281.34 294.54 259.18 331.61 233.5 375)
    (send p curve-to 198.21 434.63 164.68 505.6 125.5 564)
    (send p line-to 135 572)
    p))
 
(define left-logo-path
  (let ([p (new dc-path%)])
    (send p append left-lambda-path)
    (send p arc 0 0 630 630 (* 47/72 2 3.14) (* 121/360 2 3.14) #f)
    p))
 
(define bottom-lambda-path
  (let ([p (new dc-path%)])
    (send p move-to 135 572)
    (send p line-to 188.5 564)
    (send p curve-to 208.5 517 230.91 465.21 251 420)
    (send p curve-to 267 384 278.5 348 296.5 312)
    (send p curve-to 301.01 302.98 318 258 329 274)
    (send p curve-to 338.89 288.39 351 314 358 332)
    (send p curve-to 377.28 381.58 395.57 429.61 414 477)
    (send p curve-to 428 513 436.5 540 449.5 573)
    (send p line-to 465 580)
    (send p line-to 529 545)
    p))
 
(define bottom-logo-path
  (let ([p (new dc-path%)])
    (send p append bottom-lambda-path)
    (send p arc 0 0 630 630 (* 157/180 2 3.14) (* 47/72 2 3.14) #f)
    p))
 
(define right-lambda-path
  (let ([p (new dc-path%)])
    (send p move-to 153 44)
    (send p curve-to 192.21 30.69 233.21 14.23 275 20)
    (send p curve-to 328.6 27.4 350.23 103.08 364 151)
    (send p curve-to 378.75 202.32 400.5 244 418 294)
    (send p curve-to 446.56 375.6 494.5 456 530.5 537)
    (send p line-to 529 545)
    p))
 
(define right-logo-path
  (let ([p (new dc-path%)])
    (send p append right-lambda-path)
    (send p arc 0 0 630 630 (* 157/180 2 3.14) (* 121/360 2 3.14) #t)
    p))
 
(define lambda-path
  (let ([p (new dc-path%)])
    (send p append left-lambda-path)
    (send p append bottom-lambda-path)
    (let ([t (new dc-path%)])
      (send t append right-lambda-path)
      (send t reverse)
      (send p append t))
    (send p close)
    p))
 
(send dc translate 5 5)
(send dc scale 0.39 0.39)
 
(send dc set-smoothing 'smoothed)
 
(send dc set-pen "black" 0 'solid)
(send dc set-brush "white" 'solid)
(send dc draw-path lambda-path)
 
(send dc set-pen "black" 4 'solid)
 
(send dc set-brush "red" 'solid)
(send dc draw-path left-logo-path)
(send dc draw-path bottom-logo-path)
 
(send dc set-brush "blue" 'solid)
(send dc draw-path right-logo-path)
 
(send target save-file "14.png" 'png)

Připomeňme si, že do objektu lze poslat jednu zprávu pomocí formy send, ovšem taktéž můžeme poslat více zpráv metodou pojmenovanou send*. A právě tuto druhou metodu použijeme proto, aby se zdrojový kód příkladu zkrátil a taktéž do jisté míry zjednodušil:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define target (make-bitmap 256 256))
(define dc (new bitmap-dc% [bitmap target]))
 
(send dc set-brush "white" 'solid)
(send dc set-pen "white" 1 'transparent)
(send dc draw-rectangle 0 0 256 256)
 
(define left-lambda-path
  (let ([p (new dc-path%)])
    (send* p (move-to 153 44)
             (line-to 161.5 60)
             (curve-to 202.5 49 230 42 245 61)
             (curve-to 280.06 105.41 287.5 141 296.5 186)
             (curve-to 301.12 209.08 299.11 223.38 293.96 244)
             (curve-to 281.34 294.54 259.18 331.61 233.5 375)
             (curve-to 198.21 434.63 164.68 505.6 125.5 564)
             (line-to 135 572))
    p))
 
(define left-logo-path
  (let ([p (new dc-path%)])
    (send* p (append left-lambda-path)
             (arc 0 0 630 630 (* 47/72 2 3.14) (* 121/360 2 3.14) #f))
    p))
 
(define bottom-lambda-path
  (let ([p (new dc-path%)])
    (send* p (move-to 135 572)
             (line-to 188.5 564)
             (curve-to 208.5 517 230.91 465.21 251 420)
             (curve-to 267 384 278.5 348 296.5 312)
             (curve-to 301.01 302.98 318 258 329 274)
             (curve-to 338.89 288.39 351 314 358 332)
             (curve-to 377.28 381.58 395.57 429.61 414 477)
             (curve-to 428 513 436.5 540 449.5 573)
             (line-to 465 580)
             (line-to 529 545))
    p))
 
(define bottom-logo-path
  (let ([p (new dc-path%)])
    (send* p (append bottom-lambda-path)
             (arc 0 0 630 630 (* 157/180 2 3.14) (* 47/72 2 3.14) #f))
    p))
 
(define right-lambda-path
  (let ([p (new dc-path%)])
    (send* p (move-to 153 44)
             (curve-to 192.21 30.69 233.21 14.23 275 20)
             (curve-to 328.6 27.4 350.23 103.08 364 151)
             (curve-to 378.75 202.32 400.5 244 418 294)
             (curve-to 446.56 375.6 494.5 456 530.5 537)
             (line-to 529 545))
    p))
 
(define right-logo-path
  (let ([p (new dc-path%)])
    (send* p (append right-lambda-path)
             (arc 0 0 630 630 (* 157/180 2 3.14) (* 121/360 2 3.14) #t))
    p))
 
(define lambda-path
  (let ([p (new dc-path%)])
    (send* p (append left-lambda-path)
             (append bottom-lambda-path))
    (let ([t (new dc-path%)])
      (send t append right-lambda-path)
      (send t reverse)
      (send p append t))
    (send p close)
    p))
 
(send dc translate 5 5)
(send dc scale 0.39 0.39)
 
(send dc set-smoothing 'smoothed)
 
(send dc set-pen "black" 0 'solid)
(send dc set-brush "white" 'solid)
(send dc draw-path lambda-path)
 
(send dc set-pen "black" 4 'solid)
 
(send dc set-brush "red" 'solid)
(send dc draw-path left-logo-path)
(send dc draw-path bottom-logo-path)
 
(send dc set-brush "blue" 'solid)
(send dc draw-path right-logo-path)
 
(send target save-file "15.png" 'png)

Obrázek 15: Logo programovacího jazyka Racket vykresleného výše vypsaným příkladem.

12. Spline křivka

V knihovně je podporována i práce se spline křivkami a taktéž s Bézierovými křivkami. Nejdříve se podívejme na způsob použití spline křivky určené třemi body – dvěma body koncovými a bodem řídicím. Tato křivka se vykreslí metodou draw-spline:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define target (make-bitmap 256 256))
(define dc (new bitmap-dc% [bitmap target]))
 
(send dc set-brush "white" 'solid)
 
(send dc set-pen "white" 1 'transparent)
(send dc draw-rectangle 0 0 256 256)
 
(send dc set-smoothing 'aligned)
 
(send dc set-pen "red" 1 'long-dash)
(send dc draw-line 10 128 128 10)
(send dc draw-line 128 10 246 128)
 
(send dc set-pen "blue" 1 'solid)
(send dc draw-spline 10 130 128 12 246 130)
 
(send target save-file "16.png" 'png)

Obrázek 16: Spline křivka a její řídicí body (spojené úsečkami). Pro větší přehlednost je spline křivka posunuta o dva pixely níže, aby neležela přesně na svých řídicích úsečkách.

Poznámka: povšimněte si, že křivka prochází oběma koncovými body a bod řídicí určuje její tvar a zakřivení.

13. Nastavení alfa kanálu (průhlednosti)

Knihovna racket/draw plně podporuje alfa kanál, který lze využít jak při kreslení otevřených křivek, tak i (a to zejména) křivek uzavřených. V dalším příkladu je ukázáno, jakým způsobem se nastavuje alfa složka (tedy míra průhlednosti resp. přesněji řečeno neprůhlednosti) při vykreslování čtverců umístěných nad již nakreslený obrazec:

(define alpha 0.0)
 
(for ([y (in-range 0 4)])
     (for ([x (in-range 0 4)])
          (send dc set-alpha alpha)
          (set! alpha (+ 0.06 alpha))
          (send dc draw-rectangle (+ 10 (* x 60))
                                  (+ 10 (* y 60))
                                  50 50)))

Obrázek 17: Čtverce vykreslené červenou barvou s různou mírou průhlednosti.

Obrázek 18: Čtverce vykreslené zelenou barvou s různou mírou průhlednosti.

Obrázek 19: Čtverce vykreslené modrou barvou s různou mírou průhlednosti.

Obrázek 20: Čtverce vykreslené černou barvou s různou mírou průhlednosti.

Úplný zdrojový kód tohoto příkladu vypadá následovně:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define (draw-example color filename)
    (define target (make-bitmap 256 256))
    (define dc (new bitmap-dc% [bitmap target]))
 
    (send dc set-brush "white" 'solid)
    (send dc set-pen "white" 1 'transparent)
    (send dc draw-rectangle 0 0 256 256)
 
 
    (send dc set-pen "black" 1 'solid)
    (send dc set-smoothing 'aligned)
 
    (for ([i (in-range 0 256 10)])
         (send dc draw-line 255 0 i i)
         (send dc draw-line 0 i i 255))
 
 
    (send dc set-brush color 'solid)
 
    (define alpha 0.0)
 
    (for ([y (in-range 0 4)])
         (for ([x (in-range 0 4)])
              (send dc set-alpha alpha)
              (set! alpha (+ 0.06 alpha))
              (send dc draw-rectangle (+ 10 (* x 60))
                                      (+ 10 (* y 60))
                                      50 50)))
 
    (send target save-file filename 'png))
 
(draw-example "red"   "17A.png")
(draw-example "green" "17B.png")
(draw-example "blue"  "17C.png")
(draw-example "black" "17D.png")

14. Vykreslení textu

Do rastrových obrázků lze pochopitelně vykreslovat i text. Nejprve je však vhodné nastavit font (řez písma), jeho velikost, váhu atd.:

(send dc set-font (make-font #:size 60 #:family 'swiss #:weight 'bold))

Následně se text vykreslí stejným způsobem jako ostatní entity:

(send dc set-text-foreground "red")
(send dc draw-text "Hello" 16 20)
 
(send dc set-text-foreground "blue")
(send dc draw-text "Hello" 16 140)

Výsledek:

Obrázek 21: Text vykreslený do bitmapového obrázku.

Opět pochopitelně následuje výpis zdrojového kódu demonstračního příkladu:

#lang racket/base
 
(require racket/class)
(require racket/draw)
 
(define (draw-example filename)
    (define target (make-bitmap 256 256))
    (define dc (new bitmap-dc% [bitmap target]))
 
    (send dc set-brush "white" 'solid)
    (send dc set-pen "white" 1 'transparent)
    (send dc draw-rectangle 0 0 256 256)
 
 
    (send dc set-pen "black" 1 'solid)
    (send dc set-smoothing 'aligned)
 
    (for ([i (in-range 0 256 10)])
         (send dc draw-line 255 0 i i)
         (send dc draw-line 0 i i 255))
 
    (send dc set-alpha 0.6)
    (send dc set-font (make-font #:size 60 #:family 'swiss #:weight 'bold))
 
    (send dc set-text-foreground "red")
    (send dc draw-text "Hello" 16 20)
 
    (send dc set-text-foreground "blue")
    (send dc draw-text "Hello" 16 140)
 
    (send target save-file filename 'png))
 
(draw-example "18.png")

15. Želví grafika

V jazyku Racket existuje i několik knihoven určených pro kreslení s využitím želví grafiky, které jsme se věnovali v samostatném článku. Základní knihovna určená pro tuto oblast se jmenuje graphics/turtles. Podívejme se nyní jen na několik základních příkladů.

Vykreslení čtverce:

#lang racket/base
 
(require graphics/turtles)
 
(turtles)
 
(draw 100)
(turn 90)
 
(draw 100)
(turn 90)
 
(draw 100)
(turn 90)
 
(draw 100)
(turn 90)
 
(turtles #f)
(save-turtle-bitmap "19.png" 'png)

Obrázek 22: Čtverec vykreslený pomocí želví grafiky.

Poznámka: ve chvíli zavolání funkce turtles se zobrazí grafické okno s GUI a kreslicí plochou.

Vykreslení mnohoúhelníku se 72 hranami (takže se podobá kružnici):

#lang racket/base
 
(require graphics/turtles)
 
(turtles)
 
(define (repeat count function)
  (for ((i (in-range count)))
       (function)))
 
(repeat 72
        (lambda ()
          (turn 5)
          (draw 15)))
 
(turtles #f)
(save-turtle-bitmap "20.png" 'png)

Obrázek 23: Mnohoúhelník se 72 hranami.

Stejný příklad, ovšem želva byla posunuta o 100 pixelů ve vertikálním směru (na obrázku to není patrné, ale při zobrazení GUI se celý mnohoúhelník/kružnice posune do středu okna:

#lang racket/base
 
(require graphics/turtles)
 
(turtles)
 
(move-offset 0 100)
 
(define (repeat count function)
  (for ((i (in-range count)))
       (function)))
 
(repeat 72
        (lambda ()
          (turn 5)
          (draw 15)))
 
(turtles #f)
(save-turtle-bitmap "21.png" 'png)

Obrázek 24: Mnohoúhelník se 72 hranami.

16. Použití funkce repeat pro vykreslení složitějších obrazců

V programovacím jazyku Logo se velmi často používá příkaz repeat pro opakované volání stejného kódu, v němž se ovšem mění stav samotné želvy (viz například příklad uvedený zde nebo zde, popř. popis uvedený v tomto článku). Tento příkaz můžeme odsimulovat i v jazyku Racket:

(define (repeat count function)
  (for ((i (in-range count))) (function)))

Příklad použití, v němž je repeat třikrát zanořen:

#lang racket/base
 
(require graphics/turtles)
 
(turtles)
 
(define (repeat count function)
  (for ((i (in-range count))) (function)))
 
(repeat 36
        (lambda ()
          (turn 10)
          (repeat 10
                  (lambda ()
                    (turn 36)
                    (draw 80)
                    (repeat 3
                            (lambda ()
                              (draw 30)
                              (turn 120)))))))
 
(turtles #f)
(save-turtle-bitmap "22.png" 'png)
Poznámka: povšimněte si nutnosti použití anonymní funkce – lambdy.

Obrázek 25: Obrazec vytvořený pomocí opakování příkazů s využitím repeat.

17. Další možnosti želví grafiky

S využitím funkce repeat můžeme začít vytvářet i složitější obrazce:

#lang racket/base
 
(require graphics/turtles)
 
(turtles)
 
(define (repeat count function)
  (for ((i (in-range count))) (function)))
 
(repeat 36
        (lambda ()
          (turn 10)
          (repeat 36
                  (lambda ()
                    (turn 10)
                    (draw 20)))))
 
(turtles #f)
(save-turtle-bitmap "23.png" 'png)

Obrázek 26: Obrazec vytvořený pomocí opakování příkazů s využitím repeat.

Některé knihovny a systémy pro práci s želví grafikou umožňují použít větší množství želv (tento koncept se objevil například i ve stařičkém Atari Logu pro osmibitové mikropočítače Atari, kde pro tento účel sloužila funkce TELL). Jakmile je vytvořena další želva (či želvy), budou všechny želvy reagovat na další příkazy pro posun, kreslení, otočení atd. Vytvoření želvy se provádí funkcí:

(split ...)

Důležité je, že se této funkci může přidat příkaz pro posun či pro otočení želvy. Nová želva tedy nebude zcela totožná s původní želvou nebo želvami. Ukažme si nyní použití několika želv, které budou postupně vytvářeny a budou postupně kreslit části výsledného obrazce:

#lang racket/base
 
(require graphics/turtles)
 
(turtles)
 
(define (repeat count function)
  (for ((i (in-range count))) (function)))
 
(repeat 6
        (lambda ()
          (turn 60)
          (split (move 10))
          (repeat 36
                  (lambda ()
                    (turn 10)
                    (draw 20)))))
 
(turtles #f)
(save-turtle-bitmap "24.png" 'png)

Obrázek 27: Obrazec vykreslený několika želvami.

Poznámka: souběžná práce s více želvami má jeden velmi nepříjemný důsledek – celé vykreslování se velmi podstatným způsobem zpomalí. Již při použití desíti želv je zpomalení citelné. Z tohoto důvodu je vhodné udržovat počet želv na relativně malých hodnotách.

V dnešním posledním demonstračním příkladu použijeme pomocnou funkci nazvanou radial-turtles, kterou nalezneme v knihovně graphics/turtle-examples. Tato funkce slouží pro vytvoření stanoveného počtu želv, které jsou rozmístěny po kružnici. Poté, co všem těmto želvám zadáme vykreslení hvězdy, vznikne následující obrazec:

Obrázek 28: Obrazec vykreslený několika želvami.

Zdrojový kód příkladu, v němž je použita výše zmíněná funkce , vypadá následovně:

#lang racket/base
 
(require graphics/turtles)
(require graphics/turtle-examples)
 
(turtles)
 
(define (repeat count function)
  (for ((i (in-range count))) (function)))
 
(radial-turtles 5)
 
(move 120)
 
(repeat 6
        (lambda ()
            (draw 30)
            (turn 144)))
 
(turtles #f)
(save-turtle-bitmap "25.png" 'png)

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

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

# Příklad Popis příkladu Cesta
1 01-line.rkt vykreslení úseček do bitmapy https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/01-line.rkt
2 02-rectangle.rkt vykreslení vyplněného obdélníku https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/02-rectangle.rkt
3 03-basic-styles.rkt základní styly použité při vykreslování https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/03-basic-styles.rkt
4 04-no-smoothing.rkt úsečky vykreslené bez použití antialiasingu https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/04-no-smoothing.rkt
5 05-smoothed.rkt úsečky vykreslené s použitím antialiasingu (první metoda) https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/05-smoothed.rkt
6 06-aligned.rkt úsečky vykreslené s použitím antialiasingu (druhá metoda) https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/06-aligned.rkt
7 07-smoothed-horlines.rkt porovnání dvou podporovaných metod antialiasingu https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/07-smoothed-horlines.rkt/
8 08-aligned-horlines.rkt porovnání dvou podporovaných metod antialiasingu https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/08-aligned-horlines.rkt
9 09-pen-styles.rkt styly kreslení perem https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/09-pen-styles.rkt
10 10-pen-cap.rkt ukončení úseček a dalších typů segmentů https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/10-pen-cap.rkt
11 11-brushes.rkt styly vyplňování štětcem https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/11-brushes.rkt
12 12-gradient.rkt gradientní barvové přechody https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/12-gradient.rkt
13 13-paths.rkt základ práce s cestami https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/13-paths.rkt
14 14-racket-logo.rkt vykreslení loga Racketu, první verze https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/14-racket-logo.rkt
15 15-racket-logo.rkt vykreslení loga Racketu, druhá verze https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/15-racket-logo.rkt
16 16-spline.rkt spline křivky https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/16-spline.rkt
17 17-alpha.rkt využití alfa kanálu při kreslení poloprůhledných objektů https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/17-alpha.rkt
18 18-text.rkt vykreslení textu do bitmapy https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/18-text.rkt
19 19-turtles.rkt želví grafika, posun želvy a otočení želvy https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/19-turtles.rkt
20 20-turtles-repeat.rkt želví grafika a opakování příkazů funkcí repeat https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/20-turtles-repeat.rkt
21 21-turtles-move-offset.rkt použití funkce move-offset pro relativní posun želvy https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/21-turtles-move-offset.rkt
22 22-turtles-nested-repeats.rkt vnořené „smyčky“ typu repeat https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/22-turtles-nested-repeats.rkt
23 23-turtles-no-split.rkt vykreslení obrazce jednou želvou https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/23-turtles-no-split.rkt
24 24-turtles-split.rkt vykreslení obrazce více želvami https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/24-turtles-split.rkt
25 25-radial-turtles.rkt vykreslení obrazce více želvami, každá je natočena jiným směrem https://github.com/tisnik/lisp-families/blob/master/racket/graphics-libraries/25-radial-turtles.rkt

19. Literatura

  1. Peter Seibel
    „Practical Common Lisp“
    2009
  2. Paul Graham
    „ANSI Common Lisp“
    1995
  3. Gerald Gazdar
    „Natural Language Processing in Lisp: An Introduction to Computational Linguistics“
    1989
  4. Peter Norvig
    „Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp“
    1991
  5. Alex Mileler et.al.
    „Clojure Applied: From Practice to Practitioner“
    2015
  6. „Living Clojure: An Introduction and Training Plan for Developers“
    2015
  7. Dmitri Sotnikov
    „Web Development with Clojure: Build Bulletproof Web Apps with Less Code“
    2016
  8. McCarthy
    „Recursive functions of symbolic expressions and their computation by machine, part I“
    1960
  9. R. Kent Dybvig
    „The Scheme Programming Language“
    2009
  10. Max Hailperin
    „Concrete Abstractions“
    1998
  11. Guy L. Steele
    „History of Scheme“
    2006, Sun Microsystems Laboratories
  12. Kolář J., Muller K.:
    „Speciální programovací jazyky“
    Praha 1981
  13. „AutoLISP Release 9, Programmer's reference“
    Autodesk Ltd., October 1987
  14. „AutoLISP Release 10, Programmer's reference“
    Autodesk Ltd., September 1988
  15. McCarthy, John; Abrahams, Paul W.; Edwards, Daniel J.; Hart, Timothy P.; Levin, Michael I.
    „LISP 1.5 Programmer's Manual“
    MIT Press. ISBN 0 262 130 1 1 4
  16. Carl Hewitt; Peter Bishop and Richard Steiger
    „A Universal Modular Actor Formalism for Artificial Intelligence“
    1973
  17. Feiman, J.
    „The Gartner Programming Language Survey (October 2001)“
    Gartner Advisory
  18. Harold Abelson, Gerald Jay Sussman, Julie Sussman:
    Structure and Interpretation of Computer Programs
    MIT Press. 1985, 1996 (a možná vyšel i další přetisk)
  19. Paul Graham
    On Lisp
    Prentice Hall, 1993
    Dostupné online na stránce http://www.paulgraham.com/on­lisptext.html
  20. David S. Touretzky
    Common LISP: A Gentle Introduction to Symbolic Computation (Dover Books on Engineering)
  21. Peter Norvig
    Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp
  22. Patrick Winston, Berthold Horn
    Lisp (3rd Edition)
    ISBN-13: 978–0201083194, ISBN-10: 0201083191
  23. Matthias Felleisen, David Van Horn, Dr. Conrad Barski
    Realm of Racket: Learn to Program, One Game at a Time!
    ISBN-13: 978–1593274917, ISBN-10: 1593274912
  24. Graham Hutton
    A tutorial on the universality andexpressiveness of fold
    http://www.cs.nott.ac.uk/~pszgmh/fol­d.pdf

20. Odkazy na Internetu

  1. Racket: programovací jazyk a současně i platforma pro vývoj nových jazyků
    https://www.root.cz/clanky/racket-programovaci-jazyk-a-soucasne-i-platforma-pro-vyvoj-novych-jazyku/
  2. Makra v Racketu i v dalších lispovských jazycích
    https://www.root.cz/clanky/makra-v-racketu-i-v-dalsich-lispovskych-jazycich/
  3. Základní knihovna jazyka Racket
    https://www.root.cz/clanky/zakladni-knihovna-jazyka-racket/
  4. Grafický metaformát PostScript
    https://www.root.cz/clanky/graficky-metaformat-postscript/
  5. Vektorový grafický formát SVG
    https://www.root.cz/clanky/vektorovy-graficky-format-svg/
  6. The Racket Drawing Toolkit
    https://docs.racket-lang.org/draw/index.html
  7. Traditional Turtles
    https://docs.racket-lang.org/turtles/Traditio­nal_Turtles.html
  8. [racket] How best to repeat a function call n times?
    https://lists.racket-lang.org/users/archive/2014-September/064203.html
  9. Racket: Macros
    https://www.it.uu.se/edu/cou­rse/homepage/avfunpro/ht13/lec­tures/Racket-3-Macros.pdf
  10. Beautiful Racket / explainers: Macros
    https://beautifulracket.com/ex­plainer/macros.html
  11. Macros (dokumentace k Racketu)
    https://docs.racket-lang.org/guide/macros.html
  12. Model syntaxe jazyka Racket
    https://docs.racket-lang.org/reference/syntax-model.html
  13. Syntax Objects
    https://docs.racket-lang.org/guide/stx-obj.html
  14. Tech behind Tech: Clojure Macros Simplified
    http://techbehindtech.com/2010/09/28/clo­jure-macros-simplified/
  15. Fatvat – Exploring functional programming: Clojure Macros
    http://www.fatvat.co.uk/2009/02/clo­jure-macros.html
  16. Beautiful Racket: an introduction to language-oriented programming using Racket
    https://beautifulracket.com/
  17. Stránky projektu Racket
    https://racket-lang.org/
  18. Dokumentace k projektu Racket
    https://docs.racket-lang.org/index.html
  19. Seznam dostupných balíčků pro Racket
    https://pkgs.racket-lang.org/
  20. Racket na Wikipedii
    https://en.wikipedia.org/wi­ki/Racket_(programming_lan­guage)
  21. Blogy o Racketu a navazujících technologiích
    https://blog.racket-lang.org/
  22. Prográmky psané v Racketu na RosettaCode
    http://rosettacode.org/wi­ki/Category:Racket
  23. Fear of Macros
    https://www.greghendershott.com/fear-of-macros/
  24. Rackjure
    https://github.com/greghen­dershott/rackjure
  25. Matthew Flatt’s proposal to change Racket’s s-expressions based syntax to infix representation creates a stir in the community
    https://hub.packtpub.com/matthew-flatts-proposal-to-change-rackets-s-expressions-based-syntax-to-infix-representation-creates-a-stir-in-the-community/
  26. Racket News
    https://racket-news.com/
  27. Racket: Lisp for learning
    https://lwn.net/Articles/795385/
  28. Future of Racket
    https://www.greghendershot­t.com/2019/07/future-of-racket.html
  29. Kawa: Compiling Scheme to Java
    https://www.mit.edu/afs.new/sip­b/project/kawa/doc/kawa-tour.html
  30. Kawa in Languages shootout
    http://per.bothner.com/blog/2010/Kawa-in-shootout/
  31. Kawa 2.0 Supports Scheme R7RS
    https://developers.slashdot­.org/story/14/12/13/2259225/ka­wa-20-supports-scheme-r7rs/
  32. Kawa — fast scripting on the Java platform
    https://lwn.net/Articles/623349/
  33. Tail call (a její optimalizace)
    https://en.wikipedia.org/wi­ki/Tail_call
  34. SLIME (Wikipedia)
    http://en.wikipedia.org/wiki/SLIME
  35. slime.vim
    http://s3.amazonaws.com/mps/slime.vim
  36. What are the best scheme implementations?
    https://www.slant.co/topic­s/5282/~scheme-implementations
  37. Bigloo homepage
    http://www-sop.inria.fr/mimosa/fp/Bigloo/
  38. FTP s tarbally Bigloo
    ftp://ftp-sop.inria.fr/indes/fp/Bigloo
  39. GOTO 2018 • Functional Programming in 40 Minutes • Russ Olsen
    https://www.youtube.com/wat­ch?v=0if71HOyVjY
  40. TinyScheme (stránka na Sourceforge)
    http://tinyscheme.sourcefor­ge.net/home.html
  41. Embedding Tiny Scheme in a Game
    http://www.silicondelight­.com/embedding-tiny-scheme-in-a-game/
  42. Embedding Scheme for a game mission scripting DSL
    http://carloscarrasco.com/embedding-scheme-for-a-game-mission-scripting-dsl.html
  43. Všechny verze TinyScheme na SourceForge
    https://sourceforge.net/pro­jects/tinyscheme/files/ti­nyscheme/
  44. Fork TinyScheme na GitHubu
    https://github.com/yawnt/tinyscheme
  45. Ackermannova funkce
    https://cs.wikipedia.org/wi­ki/Ackermannova_funkce
  46. Ackermann function na Rosetta Code
    https://rosettacode.org/wi­ki/Ackermann_function#Sche­me
  47. Success Stories (lisp.org)
    https://lisp-lang.org/success/
  48. Allegro Common Lisp Success Stories
    https://franz.com/success/
  49. Clojure Success Stories
    https://clojure.org/commu­nity/success_stories
  50. Scheme Quick Reference
    https://www.st.cs.uni-saarland.de/edu/config-ss04/scheme-quickref.pdf
  51. Slajdy o Scheme (od slajdu číslo 15)
    https://docs.google.com/pre­sentation/d/1abmDnKjrq1tcjGvvRNAK­hOiSTSE2lyagtcEPal07Gbo/e­dit
  52. Scheme Cheat Sheet
    https://github.com/smythp/scheme-cheat-sheet
  53. Embedding Lua, embedding Guile
    http://puntoblogspot.blog­spot.com/2013/04/embedding-lua-embedding-guile.html
  54. Lambda Papers
    https://en.wikisource.org/wi­ki/Lambda_Papers
  55. Revised7Report on the Algorithmic Language Scheme
    https://small.r7rs.org/at­tachment/r7rs.pdf
  56. Video Lectures (MIT, SICP 2005)
    https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6–001-structure-and-interpretation-of-computer-programs-spring-2005/video-lectures/
  57. Why is Scheme my first language in university?
    https://softwareengineerin­g.stackexchange.com/questi­ons/115252/why-is-scheme-my-first-language-in-university
  58. The Perils of JavaSchools
    https://www.joelonsoftware­.com/2005/12/29/the-perils-of-javaschools-2/
  59. How to Design Programs, Second Edition
    https://htdp.org/2019–02–24/index.html
  60. LilyPond
    http://lilypond.org/
  61. LilyPond — Extending (přes Scheme)
    http://lilypond.org/doc/v2­.18/Documentation/extendin­g/scheme-tutorial
  62. Scheme in LilyPond
    http://lilypond.org/doc/v2­.18/Documentation/extendin­g/scheme-in-lilypond
  63. GnuCash
    http://www.gnucash.org/
  64. Custom Reports (in GNU Cash)
    https://wiki.gnucash.org/wi­ki/Custom_Reports
  65. Program by Design
    https://programbydesign.org/
  66. SchemePy
    https://pypi.org/project/SchemePy/
  67. LISP FQA: Section – [1–5] What is the „minimal“ set of primitives needed for a Lisp interpreter?
    http://www.faqs.org/faqs/lisp-faq/part1/section-6.html
  68. femtolisp
    https://github.com/JeffBe­zanson/femtolisp
  69. (How to Write a (Lisp) Interpreter (in Python))
    http://norvig.com/lispy.html
  70. Repositář s Guile Emacsem
    http://git.hcoop.net/?p=bpt/guile.git
  71. Interacting with Guile Compound Data Types in C
    http://www.lonelycactus.com/gu­ilebook/x1555.html
  72. Calling Guile functions from C
    http://www.lonelycactus.com/gu­ilebook/c1204.html#SECCAL­LGUILEFUNC
  73. Arrays, and other compound data types
    http://www.lonelycactus.com/gu­ilebook/charrays.html
  74. Interacting with Guile Compound Data Types in C
    http://www.lonelycactus.com/gu­ilebook/x1555.html
  75. Guile Reference Manual
    https://www.gnu.org/softwa­re/guile/manual/html_node/in­dex.html
  76. Scheme: Summary of Common Syntax
    https://www.gnu.org/softwa­re/guile/manual/html_node/Syn­tax-Summary.html#Syntax-Summary
  77. Scripting with Guile: Extension language enhances C and Scheme
    https://www.ibm.com/develo­perworks/library/l-guile/index.html
  78. Having fun with Guile: a tutorial
    http://dustycloud.org/misc/guile-tutorial.html
  79. Guile: Loading Readline Support
    https://www.gnu.org/softwa­re/guile/manual/html_node/Lo­ading-Readline-Support.html#Loading-Readline-Support
  80. lispy
    https://pypi.org/project/lispy/
  81. Lython
    https://pypi.org/project/Lython/
  82. Lizpop
    https://pypi.org/project/lizpop/
  83. Budoucnost programovacích jazyků
    http://www.knesl.com/budoucnost-programovacich-jazyku
  84. LISP Prolog and Evolution
    http://blog.samibadawi.com/2013/05/lisp-prolog-and-evolution.html
  85. List of Lisp-family programming languages
    https://en.wikipedia.org/wi­ki/List_of_Lisp-family_programming_languages
  86. clojure_py na indexu PyPi
    https://pypi.python.org/py­pi/clojure_py
  87. PyClojure
    https://github.com/eigenhom­bre/PyClojure
  88. Hy na GitHubu
    https://github.com/hylang/hy
  89. Hy: The survival guide
    https://notes.pault.ag/hy-survival-guide/
  90. Hy běžící na monitoru terminálu společnosti Symbolics
    http://try-hy.appspot.com/
  91. Welcome to Hy’s documentation!
    http://docs.hylang.org/en/stable/
  92. Hy na PyPi
    https://pypi.org/project/hy/#des­cription
  93. Getting Hy on Python
    https://lwn.net/Articles/596626/
  94. Programming Can Be Fun with Hy
    https://opensourceforu.com/2014/02/pro­gramming-can-fun-hy/
  95. Přednáška o projektu Hy (pětiminutový lighttalk)
    http://blog.pault.ag/day/2013/04/02
  96. Hy (Wikipedia)
    https://en.wikipedia.org/wiki/Hy
  97. GNU Emacs Lisp Reference Manual: Point
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Point.html
  98. GNU Emacs Lisp Reference Manual: Narrowing
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Narrowing.html
  99. GNU Emacs Lisp Reference Manual: Functions that Create Markers
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Creating-Markers.html
  100. GNU Emacs Lisp Reference Manual: Motion
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Motion.html#Motion
  101. GNU Emacs Lisp Reference Manual: Basic Char Syntax
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Basic-Char-Syntax.html
  102. Elisp: Sequence: List, Array
    http://ergoemacs.org/emac­s/elisp_list_vs_vector.html
  103. Elisp: Property List
    http://ergoemacs.org/emac­s/elisp_property_list.html
  104. Elisp: Hash Table
    http://ergoemacs.org/emac­s/elisp_hash_table.html
  105. Elisp: Association List
    http://ergoemacs.org/emac­s/elisp_association_list.html
  106. The mapcar Function (An Introduction to Programming in Emacs Lisp)
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­intr/mapcar.html
  107. Anaphoric macro
    https://en.wikipedia.org/wi­ki/Anaphoric_macro
  108. Some Common Lisp Loop Macro Examples
    https://www.youtube.com/wat­ch?v=3yl8o6r_omw
  109. A Guided Tour of Emacs
    https://www.gnu.org/softwa­re/emacs/tour/
  110. The Roots of Lisp
    http://www.paulgraham.com/ro­otsoflisp.html
  111. Evil (Emacs Wiki)
    https://www.emacswiki.org/emacs/Evil
  112. Evil (na GitHubu)
    https://github.com/emacs-evil/evil
  113. Evil (na stránkách repositáře MELPA)
    https://melpa.org/#/evil
  114. Evil Mode: How I Switched From VIM to Emacs
    https://blog.jakuba.net/2014/06/23/e­vil-mode-how-to-switch-from-vim-to-emacs.html
  115. GNU Emacs (home page)
    https://www.gnu.org/software/emacs/
  116. GNU Emacs (texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?GnuEmacs
  117. An Introduction To Using GDB Under Emacs
    http://tedlab.mit.edu/~dr/gdbin­tro.html
  118. An Introduction to Programming in Emacs Lisp
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­intr/index.html
  119. 27.6 Running Debuggers Under Emacs
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­macs/Debuggers.html
  120. GdbMode
    http://www.emacswiki.org/e­macs/GdbMode
  121. Emacs (Wikipedia)
    https://en.wikipedia.org/wiki/Emacs
  122. Emacs timeline
    http://www.jwz.org/doc/emacs-timeline.html
  123. Emacs Text Editors Family
    http://texteditors.org/cgi-bin/wiki.pl?EmacsFamily
  124. Vrapper aneb spojení možností Vimu a Eclipse
    https://mojefedora.cz/vrapper-aneb-spojeni-moznosti-vimu-a-eclipse/
  125. Vrapper aneb spojení možností Vimu a Eclipse (část 2: vyhledávání a nahrazování textu)
    https://mojefedora.cz/vrapper-aneb-spojeni-moznosti-vimu-a-eclipse-cast-2-vyhledavani-a-nahrazovani-textu/
  126. Emacs/Evil-mode – A basic reference to using evil mode in Emacs
    http://www.aakarshnair.com/posts/emacs-evil-mode-cheatsheet
  127. From Vim to Emacs+Evil chaotic migration guide
    https://juanjoalvarez.net/es/de­tail/2014/sep/19/vim-emacsevil-chaotic-migration-guide/
  128. Introduction to evil-mode {video)
    https://www.youtube.com/wat­ch?v=PeVQwYUxYEg
  129. EINE (Emacs Wiki)
    http://www.emacswiki.org/emacs/EINE
  130. EINE (Texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?EINE
  131. ZWEI (Emacs Wiki)
    http://www.emacswiki.org/emacs/ZWEI
  132. ZWEI (Texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?ZWEI
  133. Zmacs (Wikipedia)
    https://en.wikipedia.org/wiki/Zmacs
  134. Zmacs (Texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?Zmacs
  135. TecoEmacs (Emacs Wiki)
    http://www.emacswiki.org/e­macs/TecoEmacs
  136. Micro Emacs
    http://www.emacswiki.org/e­macs/MicroEmacs
  137. Micro Emacs (Wikipedia)
    https://en.wikipedia.org/wi­ki/MicroEMACS
  138. EmacsHistory
    http://www.emacswiki.org/e­macs/EmacsHistory
  139. Seznam editorů s ovládáním podobným Emacsu či kompatibilních s příkazy Emacsu
    http://www.finseth.com/emacs.html
  140. evil-numbers
    https://github.com/cofi/evil-numbers
  141. Debuggery a jejich nadstavby v Linuxu (1.část)
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu/
  142. Debuggery a jejich nadstavby v Linuxu (2.část)
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-2-cast/
  143. Debuggery a jejich nadstavby v Linuxu (3): Nemiver
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-3-nemiver/
  144. Debuggery a jejich nadstavby v Linuxu (4): KDbg
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-4-kdbg/
  145. Debuggery a jejich nadstavby v Linuxu (5): ladění aplikací v editorech Emacs a Vim
    https://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-5-ladeni-aplikaci-v-editorech-emacs-a-vim/
  146. Org mode
    https://orgmode.org/
  147. The Org Manual
    https://orgmode.org/manual/index.html
  148. Kakoune (modální textový editor)
    http://kakoune.org/
  149. Vim-style keybinding in Emacs/Evil-mode
    https://gist.github.com/tro­yp/6b4c9e1c8670200c04c16036805773d8
  150. Emacs – jak začít
    http://www.abclinuxu.cz/clan­ky/navody/emacs-jak-zacit
  151. Programovací jazyk LISP a LISP machines
    https://www.root.cz/clanky/pro­gramovaci-jazyk-lisp-a-lisp-machines/
  152. Evil-surround
    https://github.com/emacs-evil/evil-surround
  153. Spacemacs
    http://spacemacs.org/
  154. Lisp: Common Lisp, Racket, Clojure, Emacs Lisp
    http://hyperpolyglot.org/lisp
  155. Common Lisp, Scheme, Clojure, And Elisp Compared
    http://irreal.org/blog/?p=725
  156. Does Elisp Suck?
    http://irreal.org/blog/?p=675
  157. Emacs pro mírně pokročilé (9): Elisp
    https://www.root.cz/clanky/emacs-elisp/
  158. If I want to learn lisp, are emacs and elisp a good choice?
    https://www.reddit.com/r/e­macs/comments/2m141y/if_i_wan­t_to_learn_lisp_are_emacs_an­d_elisp_a/
  159. Clojure(Script) Interactive Development Environment that Rocks!
    https://github.com/clojure-emacs/cider
  160. An Introduction to Emacs Lisp
    https://harryrschwartz.com/2014/04/08/an-introduction-to-emacs-lisp.html
  161. Emergency Elisp
    http://steve-yegge.blogspot.com/2008/01/emergency-elisp.html
  162. Lambda calculus
    https://en.wikipedia.org/wi­ki/Lambda_calculus
  163. John McCarthy's original LISP paper from 1959
    https://www.reddit.com/r/pro­gramming/comments/17lpz4/joh­n_mccarthys_original_lisp_pa­per_from_1959/
  164. Micro Manual LISP
    https://www.scribd.com/do­cument/54050141/Micro-Manual-LISP
  165. How Lisp Became God's Own Programming Language
    https://twobithistory.org/2018/10/14/lis­p.html
  166. History of Lisp
    http://jmc.stanford.edu/ar­ticles/lisp/lisp.pdf
  167. The Roots of Lisp
    http://languagelog.ldc.upen­n.edu/myl/llog/jmc.pdf
  168. Racket
    https://racket-lang.org/
  169. The Racket Manifesto
    http://felleisen.org/matthi­as/manifesto/
  170. MIT replaces Scheme with Python
    https://www.johndcook.com/blog/2009/03/26/mit-replaces-scheme-with-python/
  171. Adventures in Advanced Symbolic Programming
    http://groups.csail.mit.e­du/mac/users/gjs/6.945/
  172. Why MIT Switched from Scheme to Python (2009)
    https://news.ycombinator.com/i­tem?id=14167453
  173. Starodávná stránka XLispu
    http://www.xlisp.org/
  174. AutoLISP
    https://en.wikipedia.org/wi­ki/AutoLISP
  175. Seriál PicoLisp: minimalistický a výkonný interpret Lispu
    https://www.root.cz/serialy/picolisp-minimalisticky-a-vykonny-interpret-lispu/
  176. Common Lisp
    https://common-lisp.net/
  177. Getting Going with Common Lisp
    https://cliki.net/Getting%20Started
  178. Online Tutorial (Common Lisp)
    https://cliki.net/online%20tutorial
  179. Guile Emacs
    https://www.emacswiki.org/e­macs/GuileEmacs
  180. Guile Emacs History
    https://www.emacswiki.org/e­macs/GuileEmacsHistory
  181. Guile is a programming language
    https://www.gnu.org/software/guile/
  182. MIT Scheme
    http://groups.csail.mit.e­du/mac/projects/scheme/
  183. SIOD: Scheme in One Defun
    http://people.delphiforum­s.com/gjc//siod.html
  184. CommonLispForEmacs
    https://www.emacswiki.org/e­macs/CommonLispForEmacs
  185. Elisp: print, princ, prin1, format, message
    http://ergoemacs.org/emac­s/elisp_printing.html
  186. Special Forms in Lisp
    http://www.nhplace.com/ken­t/Papers/Special-Forms.html
  187. Basic Building Blocks in LISP
    https://www.tutorialspoin­t.com/lisp/lisp_basic_syn­tax.htm
  188. Introduction to LISP – University of Pittsburgh
    https://people.cs.pitt.edu/~mi­los/courses/cs2740/Lectures/Lis­pTutorial.pdf
  189. Why don't people use LISP
    https://forums.freebsd.org/threads/why-dont-people-use-lisp.24572/
  190. Structured program theorem
    https://en.wikipedia.org/wi­ki/Structured_program_the­orem
  191. Clojure: API Documentation
    https://clojure.org/api/api
  192. Tutorial for the Common Lisp Loop Macro
    http://www.ai.sri.com/pkarp/loop.html
  193. Common Lisp's Loop Macro Examples for Beginners
    http://www.unixuser.org/~e­uske/doc/cl/loop.html
  194. A modern list api for Emacs. No 'cl required.
    https://github.com/magnars/dash.el
  195. The LOOP Facility
    http://www.lispworks.com/do­cumentation/HyperSpec/Body/06_a­.htm
  196. Clojure.org: Vars and the Global Environment
    http://clojure.org/Vars
  197. Clojure.org: Refs and Transactions
    http://clojure.org/Refs
  198. Clojure.org: Atoms
    http://clojure.org/Atoms
  199. Clojure.org: Agents as Asynchronous Actions
    http://clojure.org/agents
  200. Transient Data Structureshttp://clojure.or­g/transients
  201. Dynamic Languages Strike Back
    http://steve-yegge.blogspot.cz/2008/05/dynamic-languages-strike-back.html
  202. Scripting: Higher Level Programming for the 21st Century
    http://www.tcl.tk/doc/scripting.html
  203. Clojure (na Wikipedia EN)
    http://en.wikipedia.org/wiki/Clojure
  204. Clojure (na Wikipedia CS)
    http://cs.wikipedia.org/wiki/Clojure
  205. SICP (The Structure and Interpretation of Computer Programs)
    http://mitpress.mit.edu/sicp/
  206. Pure function
    http://en.wikipedia.org/wi­ki/Pure_function
  207. Funkcionální programování
    http://cs.wikipedia.org/wi­ki/Funkcionální_programová­ní
  208. Jazyky Hy a Clojure-py: moderní dialekty LISPu určené pro Python VM
    https://www.root.cz/clanky/jazyky-hy-a-clojure-py-moderni-dialekty-lispu-urcene-pro-python-vm/
  209. Pixie: lehký skriptovací jazyk s „kouzelnými“ schopnostmi
    https://www.root.cz/clanky/pixie-lehky-skriptovaci-jazyk-s-kouzelnymi-schopnostmi/
  210. 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/
  211. Stránka projektu Jython
    http://www.jython.org/
  212. Jython (Wikipedia)
    https://en.wikipedia.org/wiki/Jython
  213. Scripting for the Java Platform (Wikipedia)
    https://en.wikipedia.org/wi­ki/Scripting_for_the_Java_Plat­form
  214. JSR 223: Scripting for the JavaTM Platform
    https://jcp.org/en/jsr/detail?id=223
  215. List of JVM languages
    https://en.wikipedia.org/wi­ki/List_of_JVM_languages
  216. The JavaTM Virtual Machine Specification, Second Edition
    http://java.sun.com/docs/bo­oks/jvms/second_edition/html/VMSpec­TOC.doc.html
  217. The class File Format
    http://java.sun.com/docs/bo­oks/jvms/second_edition/html/Clas­sFile.doc.html
  218. javap – The Java Class File Disassembler
    http://docs.oracle.com/ja­vase/1.4.2/docs/tooldocs/win­dows/javap.html
  219. javap-java-1.6.0-openjdk(1) – Linux man page
    http://linux.die.net/man/1/javap-java-1.6.0-openjdk
  220. Using javap
    http://www.idevelopment.in­fo/data/Programming/java/mis­cellaneous_java/Using_javap­.html
  221. Examine class files with the javap command
    http://www.techrepublic.com/ar­ticle/examine-class-files-with-the-javap-command/5815354