Hlavní navigace

Kawa: překvapivě silný a výkonný dialekt Scheme pro JVM

Pavel Tišnovský

Dnes se seznámíme s projektem nazvaným Kawa. Jedná se o implementaci jazyka Scheme běžící nad JVM, která poskytuje jak překlad do bajtkódu Javy, tak i například velmi dobrou kooperaci mezi Kawa/Scheme a javovskými třídami a objekty.

Doba čtení: 43 minut

Sdílet

11. Jednotky u numerických hodnot

12. Použití jednotek v praxi při aritmetických operacích

13. Líné vyhodnocování výrazů

14. Rozhraní mezi jazyky Java a Kawa

15. Obsah následující části seriálu

16. Krátké shrnutí: seznam implementací jazyka Scheme, LISP a Clojure

17. Programovací jazyky pro JVM aneb zdaleka nejde jen o Javu

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

19. Literatura

20. Odkazy na Internetu

1. Kawa: překvapivě silný a výkonný dialekt Scheme pro JVM

V předchozích dvou částech miniseriálu o LISPovských jazycích jsme se seznámili se dvěma implementacemi programovacího jazyka Scheme. Připomeňme si, že se jednalo o projekt nazvaný GNU Guile a taktéž o nástroj TinyScheme. Oba zmíněné projekty nabízí programátorům jak klasickou interaktivní smyčku REPL, tak i možnost vložit (embed) interpret či překladač jazyka Scheme do dalších nativních aplikací a tím do značné míry rozšířit jejich možnosti (skriptovatelné aplikace, aplikace s podporou pluginů získaných od třetích stran atd.). Zatímco projekt GNU Guile obsahuje jak interpret, tak i překladač (a to relativně dobrý), je TinyScheme v tomto ohledu mnohem jednodušší, protože se jedná o „pouhý“ interpret, ovšem pochopitelně doplněný o automatickou správu paměti a další pro Scheme naprosto nezbytné vlastnosti.

Dnes se budeme zabývat další implementací jazyka Scheme. Tentokrát se jedná o projekt nazvaný Kawa, který je zajímavý a potenciálně užitečný hned z několika důvodů. Jedná se o implementaci Scheme naprogramovanou v Javě a běžící nad virtuálním strojem Javy (JVM). Ovšem současně se v žádném případě nejedná o pouhý primitivní interpret, ale o překladač jazyka Scheme do bajtkódu JVM. Z benchmarků je patrné, že výsledný kód vůbec není pomalý ale naopak dokáže více než zdárně konkurovat dalším programovacím jazykům, které v současnosti nad JVM existují. Jenže to není vše, protože Kawa dokáže velmi dobře kooperovat i se samotným ekosystémem Javy – lze v ní vytvářet instance Javovských tříd, volat jejich metody, přistupovat k atributům atd. atd. Díky tomu může být Kawa použitelná i v rozsáhlých systémech naprogramovaných v Javě (ostatně LISPovské jazyky již dlouho slouží i ve funkci „lepidel“ mezi jednotlivými částmi aplikace).

Možnosti Kawy jsou ale ještě větší – podpora pro práci s jednotkami (units) namísto „holých“ čísel, práce s kvaterniony atd. atd.

2. LISPovské jazyky pro JVM: Kawa či Clojure?

Na tomto místě si čtenáři pravděpodobně položí otázku, zda má smysl používat systém Kawa i v současnosti, kdy máme k dispozici programovací jazyk Clojure, což je dnes dokonce jeden z nejpopulárnějších LISPovských programovacích jazyků vůbec. Clojure je skutečně velmi dobrý jazyk s mnoha zajímavými myšlenkami – umožňuje a podporuje plně funkcionální přístup včetně STM (Software Transactional Memory), má knihovnu pro asynchronní volání, knihovnu pro kontrolu datových schémat, jednodušší zápis programů s méně závorkami, koncept obecných sekvencí a kolekcí, threading makra atd. Ovšem Clojure je určeno spíše pro tvorbu rozsáhlejších aplikací, u nichž využijeme celý ekosystém okolo Clojure postavený (Leiningen atd.). Navíc se musíme smířit s tím, že inicializace celého Clojure je dosti pomalá, což je patrné například už při spouštění interaktivní smyčky REPL a pochopitelně i při spouštění aplikací v případě, že je použit JIT překladač (Just in Time) a nikoli AOT překladač (Ahead of Time) do bajtkódu.

Poznámka: pokud navíc spustíme REPL příkazem lein repl, inicializují se dokonce dva virtuální stroje Javy.

Systém Kawa leží na druhé straně spektra než Clojure. Jedná se o programovací jazyk doplněný jen o naprosto základní nástroje, spouštění jeho smyčky REPL je rychlé a i překlad do bajtkódu je proveden prakticky okamžitě (což si vyzkoušíme v navazujících kapitolách). O ostatní funkcionalitu se musí postarat nástroje určené přímo pro práci s Javou (Java Archiver atd.). Tento přístup má ovšem i nevýhody, protože ekosystém postavený okolo Kawy je relativně malý, i když samotný interpret a překladač je velmi dobře podporován a i dokumentace je na vysoké úrovni (zejména v porovnání s menšími projekty typu TinyScheme).

Jen pro zajímavost se podívejme na výsledky benchmarků zveřejněných zde. Porovnáme zde výkonnost několika jazyků určených pro běh nad virtuálním strojem Javy:

# Benchmark Java Scala Clojure JRuby Kawa Kawa/FTC
1 binarytrees 1.00 1.05 1.46 1.04   27.36 1.10 3.72
2 chameneosredux 1.00 3.92 1.85 0.99 4.08   46.43 0.95 1.96
3 fannkuchredux 1.00 1.43 1.23 0.94 3.54 61.66 1.38 1.34
4 fasta 1.00 1.33 0.67 5.32 4.32 71.36 58.50 1.72 5.46
5 knucleotide 1.06 1.00 2.16 1.46 7.93 7.22 10.54 8.93 11.11 1.62 11.18 1.71
6 mandelbrot 1.00 1.01 1.06 1.09 1.19 1.16 1.10 2.28 186.49 1.05 1.05
7 meteor 2.16 1.00 13.25   41.80 26.30 1.25 2.11
8 nbody 1.00 1.23 2.25 128.50 1.03 1.05
9 pidigits 1.00 0.30 0.83   1.28 0.63 0.63
10 regexdna 1.29 1.00 1.00 1.51 1.27 1.00 1.63 4.20 2.80 1.82 1.05 1.04
11 revcomp 1.00 0.81 23.72 9.52 5.55 7.15 1.43 1.17 1.44 1.17
12 spectralnorm 1.00 1.05 1.02 1.03   137.54 174.76 1.05 8.98
13 threadring 8.07 1.00 5.84   16.02 21.03 0.96 0.96
Poznámka: rozdíl mezi Kawou a Clojure lze porovnat s rozdíly mezi jazykem Lua a Python (velikost ekosystému, základna vývojářů, univerzálnost versus specifičnost, rychlost programů apod.).

3. Instalace interpretru a překladače Kawa

Instalaci interpretu a překladače nástroje Kawa lze provést několika různými způsoby. K dispozici je již přeložená varianta projektu Kawa, která obsahuje všechny potřebné třídy a rozhraní.

Alternativně je samozřejmě možné provést překlad ručně a tím pádem například ovlivnit, jaká JVM bude podporována. Ukažme si tuto možnost. Potřebovat budeme JDK a některé další nástroje, zejména překladač jazyka C, nástroj make atd.

V prvním kroku získáme tarball se všemi potřebnými zdrojovými soubory:

$ wget ftp://ftp.gnu.org/pub/gnu/kawa/kawa-3.0.tar.gz
 
--2019-07-25 20:10:16--  ftp://ftp.gnu.org/pub/gnu/kawa/kawa-3.0.tar.gz
           => ‘kawa-3.0.tar.gz’
Resolving ftp.gnu.org (ftp.gnu.org)... 209.51.188.20, 2001:470:142:3::b
Connecting to ftp.gnu.org (ftp.gnu.org)|209.51.188.20|:21... connected.
Logging in as anonymous ... Logged in!
==> SYST ... done.    ==> PWD ... done.
==> TYPE I ... done.  ==> CWD (1) /pub/gnu/kawa ... done.
==> SIZE kawa-3.0.tar.gz ... 3393879
==> PASV ... done.    ==> RETR kawa-3.0.tar.gz ... done.
Length: 3393879 (3,2M) (unauthoritative)
 
100%[================================================================>] 3 393 879   1,66MB/s   in 2,0s
 
2019-07-25 20:10:19 (1,66 MB/s) - ‘kawa-3.0.tar.gz’ saved [3393879]

Získaný tarball běžným způsobem rozbalíme:

$ tar xvfz kawa-3.0.tar.gz

Vytvořit by se měl adresář kawa-3.0, do kterého stačí přejít:

$ cd kawa-3.0/

A spustit vlastní překlad:

$ configure
$ make

V případě potřeby je možné příkazu configure předat další nepovinné parametry, které ovlivní způsob překladu a taktéž vlastnosti výsledného interpretru a překladače sytému Kawa. Poměrně často, zejména ve chvíli, kdy je nutné udržovat velké a „starodávné“ systémy, se setkáme s požadavkem, že systém má běžet na starší verzi JVM; typicky se jedná o JRE 6 nebo 7. I Kawu lze přeložit s podporou starší JVM:

$ ./configure --with-java-source=6
$ make

Vhodné je mít v REPLu k dispozici plnohodnotnou příkazovou řádku s historií příkazů a možností editace. Pokud máte v systému nainstalovány knihovny libreadline-dev a libncurses-dev, lze to velmi snadno zařídit:

$ ./configure --with-java-source=6 --enable-kawa-frontend

Výsledkem překladu je kromě spustitelného souboru kawa i dvojice Java archivů, které nejsou nikterak velké (na druhou stranu možnosti výsledného jazyka jsou až překvapivě rozsáhlé):

$ ls -l lib
 
total 5720
-rw-r--r-- 1 tester tester 3235834 čec 25 20:27 kawa.jar
-rw-r--r-- 1 tester tester 2621426 čec 25 20:27 kawart.jar

Zkusme si nyní spustit interaktivní smyčku REPL:

$ cd bin
$ ./kawa
 
#|kawa:1|#

Dále si otestujme základní interoperabilitu s ekosystémem Javy:

#|kawa:5|# (java.util.Random 42)
java.util.Random@7cb45826

Zavolání metody System.exit je snadné:

#|kawa:6|# (java.lang.System:exit 0)

4. Nastavení pluginů Slime for Vim a Rainbow parenthesis

Pro snazší použití (nejenom) programovacího jazyka Kawa je vhodné si nastavit programátorský editor takovým způsobem, aby se co nejvíce využilo synergie mezi editorem a interaktivní smyčkou REPL. Pro Emacs pro tento účel existuje režim SLIME: The Superior Lisp Interaction Mode for Emacs, který si popíšeme v samostatném článku. Dnes se ovšem v krátkosti zaměříme na věčného konkurenta Emacsu: textový editor Vim. Popíšeme si moduly Slime for Vim a Rainbow parenthesis.

Začneme modulem Slime for Vim. Ten může pracovat různými způsoby, ovšem nejjednodušší je takové nastavení, kdy je interaktivní smyčka REPL interpretru jazyka Kawa stále spouštěna v samostatném procesu, ovšem namísto toho, aby se interpreter spouštěl v „normálním“ terminálu (resp. ve virtuálním terminálu), je spuštěn v pojmenované session nástroje screen, popř. tmux. Vzhledem k tomu, že je tato session pojmenovaná, je možné do příslušného okna poslat sekvenci znaků, které budou zpracovány stejným způsobem, jako by je uživatel napsal na klávesnici.

Pokud je již smyčka REPL programovacího jazyka Kawa spuštěna v session pojmenovaném „kawa“, lze v jiném okně či v jiném terminálu spustit samotný editor Vim a s využitím příkazu :source načíst a spustit skript slime.vim. Ideální je tento příkaz zavolat automaticky při načítání souborů s koncovkou .clj. Pokud je tento skript načten, je možné v jakémkoli okamžiku stisknout klávesovou zkratku Ctrl+C Ctrl+C. Skript se při prvním stisku této zkratky zeptá na jméno session a na okno – většinou jsou nabízené hodnoty správné, takže se jen potvrdí Enterem. Poté se již zcela automaticky celý odstavec vloží do vizuálního bloku (sekvence příkazů vip), vizuální blok se vloží do pojmenovaného registru y (sekvence příkazů "ry a nakonec se obsah tohoto registru přenese do okna, v němž běží REPL jazyka Kawa (tam se hned vyhodnotí, protože součástí přenášeného bloku je i koncový Enter).

Celý postup možná vypadá poněkud složitě, ve skutečnosti si však na tento nástroj velmi rychle zvyknete. Je ho samozřejmě možné upravovat a rozšiřovat, například využít klávesovou zkratku K (hledání slova pod kurzorem v manuálových stránkách) k tomu, aby se do REPL poslal příkaz (doc „hledané-slovo“) atd.

Podívejme se ještě na screenshoty, kde je ukázána kooperace mezi textovým editorem a interpretrem (v tomto případě intepretrem jazyka Clojure, ten se však v tomto ohledu chová stejně, jako jazyk Kawa). Pro jednoduchost používám dva terminály, stejně tak je ale možné obě okna využívat z jediného terminálu – opět s využitím nástroje screen.

obr

Obrázek 1: Textový editor Vim spuštěný v jiném terminálu (či v jiném okně nástroje screen). Přímo z Vimu je načten a proveden (spuštěn) skript slime.vim.

obr

Obrázek 2: Po prvním stisku Ctrl+C Ctrl+C se skript zeptá na jméno session (lze pouze potvrdit Enterem).

obr

Obrázek 3: Dále se zeptá na jméno okna (lze taktéž pouze potvrdit Enterem).

obr

Obrázek 4: Vybraná část programu je „magicky“ přenesena do REPL a tam vykonána.

obr

Obrázek 5: Další příklad – stlačení Ctrl+C Ctrl+C nad formou/výrazem (range 0 10) – nyní se vše provede bez dalších dotazů.

Dalším jednoduchým, ovšem v praxi velmi užitečným pluginem, je přídavný modul nazvaný Rainbow Parenthesis. Tento plugin lze využít pro barevné odlišení párových závorek popř. taktéž – což může být pro mnoho uživatelů ještě zajímavější a užitečnější – k barevnému odlišení párových tagů, například vnořených značek <div> v HTML či XHTML. Tento plugin je zcela univerzální, čímž se odlišuje od podobně zaměřených pluginů, které jsou však specializované například pro programovací jazyk Lisp, Scheme či Clojure (tj. pro jazyky, v nichž se párové závorky vyskytují s relativně vysokou frekvencí). Nejlépe si možnosti použití přídavného modulu Rainbow Parenthesis ukážeme na několika screenshotech, které jsou umístěny pod tímto odstavcem.

Obrázek 6: Zvýraznění párových závorek ve zdrojovém kódu programovacího jazyka Clojure.

Obrázek 7: Zvýraznění párových závorek ve zdrojovém kódu programovacího jazyka C.

Pro instalaci tohoto modulu lze jednoduše použít Git, protože zdrojové kódy jsou uloženy na GitHubu:

cd ~/.vim/bundle
git clone https://github.com/luochen1990/rainbow
Cloning into 'rainbow'...
remote: Counting objects: 308, done.
remote: Total 308 (delta 0), reused 0 (delta 0), pack-reused 308
Receiving objects: 100% (308/308), 604.24 KiB | 628.00 KiB/s, done.
Resolving deltas: 100% (113/113), done.

Výsledná struktura adresáře ~/.vim/ by nyní měla vypadat následovně:

.
├── autoload
├── bundle
│   ├── calendar
│   │   ├── autoload
│   │   ├── doc
│   │   └── plugin
│   ├── rainbow
│   │   └── plugin
│   └── vim-fugitive
│       ├── doc
│       └── plugin
└── spell

Dále je nutné do konfiguračního souboru .vimrc přidat tento řádek:

let g:rainbow_active = 1

Funkce pluginu Rainbow Parentheses se projeví po novém startu editoru.

Plugin Rainbow Parentheses pracuje zcela automaticky po otevření každého souboru, pro nějž je v modulu zadefinováno, které znaky či skupiny znaků se mají považovat za párové závorky. K dispozici je jeden příkaz pro zapnutí či vypnutí funkce tohoto pluginu:

Příkaz Význam
:RainbowToggle zapnutí či vypnutí barevného zvýraznění párových závorek

Nastavení pluginu (lze změnit editací zdrojového skriptu):

Soubor Párové závorky
* (platné pro LISP i Scheme) () [] {}
*.tex () []
*.vim () [] {}
*.xml <jméno-tagu </
*.xhtml <jméno-tagu </
*.html dtto kromě několika vybraných nepárových tagů typu <br> atd.

Obrázek 3: Zvýraznění párových tagů v HTML dokumentu.

Obrázek 4: Zákaz zvýraznění párových tagů v HTML dokumentu příkazem :RainbowToggle.

5. Základní vlastnosti dialektu Scheme implementovaného v systému Kawa

Systém Kawa se v prakticky všech ohledech podobá klasickému Scheme popsanému v RnRS. Základní vlastnosti tohoto programovacího jazyka již známe, takže si jen krátce zopakujme některé užitečné tipy a triky.

Definice nové pojmenované funkce pro tisk libovolné hodnoty na standardní výstup:

(define (print item)
     (display item)
     (newline))

Práce s takzvanými tečka-dvojicemi a vztah mezi sekvencí tečka-dvojic a seznamy:

(print '(1 . 2))
 
(print '(1 . ((2 . 3) . 4)))
 
(print '((1 . 2) . (3 . 4)))
 
(print '(1 . (2 . (3 . nil))))
 
; this is proper list
(print '(1 . (2 . (3 . ()))))

Výsledek činnosti předchozího skriptu:

(1 . 2)
(1 (2 . 3) . 4)
((1 . 2) 3 . 4)
(1 2 3 . nil)
(1 2 3)

Použití funkce cons při konstrukci tečka dvojic a/nebo seznamů:

(print (cons 1 2))
 
(print (cons 1 (cons 2 3)))
 
(print '((1 . 2) . (3 . 4)))
 
; this is proper list
(print (cons 1 (cons 2 (cons 3 '()))))
 
(define nil '())
 
; this is proper list
(print (cons 1 (cons 2 (cons 3 nil))))

Výsledek činnosti předchozího skriptu:

(1 . 2)
(1 2 . 3)
((1 . 2) 3 . 4)
(1 2 3)
(1 2 3)

Vytvoření filtru (funkce vyššího řádu, která akceptuje jinou funkci jako svůj vstup):

(define (filter pred lst)
  (cond ((null? lst) '())
        ((pred (car lst))
         (cons (car lst) (filter pred (cdr lst))))
        (else (filter pred (cdr lst)))))

Použití lambda-výrazu (anonymní funkce) a vytvoření uzávěru (closure):

(define (larger-than limit)
    (lambda (value) (> value limit)))

Praktické použití obou výše definovaných funkcí filter a larger-than:

(print (filter (larger-than 5) '(1 2 3 4 5 6 7 8 9 10)))
 
(define (larger-than-five)
     (larger-than 5))
 
(print (filter (larger-than-five) '(1 2 3 4 5 6 7 8 9 10)))
 
(print ((larger-than 5) 0))
(print ((larger-than 5) 10))
 
(print ((larger-than-five) 0))
(print ((larger-than-five) 10))

Výsledek první i druhé aplikace funkce filter:

(6 7 8 9 10)

6. „Numerická věž“ programovacího jazyka Scheme a její rozšíření v Kawě

V jazyku Scheme je definována takzvaná „numerická věž“, v níž je vždy jeden numerický datový typ podmnožinou typu jiného a na nejvyšším stupni hierarchie stojí obecné číslo number. Dialekt Kawa tento koncept rozšiřuje o numerický typ kvaternion, který bude popsán v navazujících kapitolách. Podívejme se nyní, jak „numerická věž“ vypadá v případě jazyka Kawa:

Typ Význam
number libovolná obecná čísla
quantity numerická hodnota i s uvedenou jednotkou (viz další text)
quaternion kvaterniony
complex komplexní čísla
real reálná čísla
rational zlomky (racionální čísla)
integer celá čísla
Poznámka: dále jsou podporovány všechny numerické typy jazyka Java.

Podívejme se nejprve na použití typu integer. Ten má obecně libovolný rozsah (tedy alespoň v jazyku Kawa):

(define (factorial n)
  (if (= n 0) ; podmínka pro ukončení rekurzivního zanořování
    1       ; faktoriál nuly je definitoricky roven jedné
    (* n (factorial (- n 1)))))
 
 
(define n 0)
 
(do ()
  ((>= n 30))
  (display (factorial n))
  (newline)
  (set! n (+ n 1)))

Výpočet faktoriálu lze provést pro prakticky libovolné n, pokud budeme mít k dispozici dostatek paměti a dostatek výpočetního výkonu:

1
1
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600
6227020800
87178291200
1307674368000
20922789888000
355687428096000
6402373705728000
121645100408832000
2432902008176640000
51090942171709440000
1124000727777607680000
25852016738884976640000
620448401733239439360000
15511210043330985984000000
403291461126605635584000000
10888869450418352160768000000
304888344611713860501504000000
8841761993739701954543616000000

7. Zlomky

Jedním ze základních numerických datových typů jazyka Scheme a taktéž i jeho implementace jazyka Kawa, jsou zlomky (ratio). Interně jsou zlomky reprezentovány dvojicí celočíselných hodnot s libovolným rozsahem, tudíž i přesnost zlomků je teoreticky libovolná (omezená kapacitou paměti i výpočetním výkonem).

Podívejme se nyní na jednoduchý příklad s dvojicí vnořených smyček, v nichž se počítají různé varianty zlomků:

(do ((y 1 (+ y 1)))    ; počáteční hodnota počitadla a iterační příkaz
  ((> y 10))           ; podmínka pro ukončení smyčky
  (do ((x 1 (+ x 1)))  ; vnitřní smyčka
    ((> x 10))         ; podmínka pro ukončení vnitřní smyčky
    (display (/ x y))  ; tisk výsledku
    (display "\t"))    ; přechod na další tabelační zarážku 
  (newline))           ; přechod na další řádek

Výsledek předchozího demonstračního příkladu by měl vypadat následovně:

1       2       3       4       5       6       7       8       9       10
1/2     1       3/2     2       5/2     3       7/2     4       9/2     5
1/3     2/3     1       4/3     5/3     2       7/3     8/3     3       10/3
1/4     1/2     3/4     1       5/4     3/2     7/4     2       9/4     5/2
1/5     2/5     3/5     4/5     1       6/5     7/5     8/5     9/5     2
1/6     1/3     1/2     2/3     5/6     1       7/6     4/3     3/2     5/3
1/7     2/7     3/7     4/7     5/7     6/7     1       8/7     9/7     10/7
1/8     1/4     3/8     1/2     5/8     3/4     7/8     1       9/8     5/4
1/9     2/9     1/3     4/9     5/9     2/3     7/9     8/9     1       10/9
1/10    1/5     3/10    2/5     1/2     3/5     7/10    4/5     9/10    1
Poznámka: povšimněte si, že funkce / (dělení) má v jazyku Kawa odlišný význam, než v některých jiných jazycích, protože podílem dvou celých hodnot vznikne zlomek a nikoli výsledek celočíselného dělení.

8. Výpočet konstanty Pi Wallisovým součinem: použití reálných čísel a zlomků

Základní vlastnosti „numerické věže“ programovacího jazyka Kawa si ukážeme na jednoduchém algoritmu určeném pro výpočet hodnoty čísla Pi s využitím takzvaného Wallisova součinu (Wallis product, viz též https://en.wikipedia.org/wi­ki/Wallis_product). Výpočet používající hodnoty s plovoucí řádovou čárkou může být implementován například takto (používáme zde programovou smyčku, i když by bylo možné algoritmus přepsat za pomoci rekurze):

(define (compute-pi n)
  (let ((pi 4.0))
    (do ((i 3 (+ i 2)))
      ((> i (+ n 2)))
      (set! pi (* pi (/ (- i 1) i) (/ (+ i 1) i))))
    pi))
 
(do ((n 1 (* n 2)))
  ((> n 10000))
  (display n)
  (display (compute-pi n))
  (newline))

Výsledky výpočtu pro různé vstupní hodnoty n:

n aproximace π
1 3.5555555555555554
2 3.5555555555555554
4 3.4133333333333336
8 3.302393550012597
16 3.230036466411716
32 3.1881271694471383
64 3.1654820600347926
128 3.1536988490957967
256 3.147686899556418
512 3.1446501625172
1024 3.143124017028185
2048 3.142358989121772
4096 3.141975985005608
8192 3.1417843602347433

Další výpočty již budou ovlivněny přesností výpočtů s plovoucí řádovou čárkou.

Nepatrnou změnou algoritmu (pouhou změnou konstanty 4.0 za 4) dosáhneme toho, že výpočty budou probíhat se zlomky a tedy i s prakticky libovolným rozsahem a přesností:

(define (compute-pi n)
  (let ((pi 4))
    (do ((i 3 (+ i 2)))
      ((> i (+ n 2)))
      (set! pi (* pi (/ (- i 1) i) (/ (+ i 1) i))))
    pi))
 
(do ((n 1 (* n 2)))
  ((> n 10000))
  (display n)
  (display (compute-pi n))
  (newline))

Nyní budou výsledky zobrazeny ve formě zlomků:

n aproximace π
1 32/9
2 32/9
4 256/75
8 65536/19845
16 4294967296/1329696225
32 18446744073709551616/5786­075364399106425
64 3402823669209384634633746­07431768211456/107497803009882761535906756719489­104425
128 1157920892373161954235709­850086879078532699846656405640394575840079131296­39936/367162797647958813215167831161162248374633­73080333115741577873817663528415625
256
512

Zlomky převedeme zpět na reálné číslo (či lépe řečeno jeho aproximaci) s využitím funkce exact->inexact:

(define (compute-pi n)
  (let ((pi 4))
    (do ((i 3 (+ i 2)))
      ((> i (+ n 2)))
      (set! pi (* pi (/ (- i 1) i) (/ (+ i 1) i))))
    pi))

(do ((n 1 (* n 2)))
  ((> n 10000))
  (display n)
  (display (exact->inexact (compute-pi n)))
  (newline))
n aproximace π
1 3.5555555555555554
2 3.5555555555555554
4 3.4133333333333336
8 3.3023935500125976
16 3.2300364664117174
32 3.18812716944714
64 3.1654820600347966
128 3.1536988490958002
256 3.1476868995564256
512 3.144650162517214
1024 3.143124017028195
2048 3.1423589891217865
4096 3.1419759850056326
8192 3.141784360234786

9. Kvaterniony a kvaternionová algebra

Programovací jazyk Kawa podporuje i výpočty s takzvanými kvaterniony, které jsou (značně zjednodušeně řečeno) zobecněním komplexních čísel. V komplexní rovině je každá číselná hodnota – neboli komplexní číslo – vyjádřeno pomocí lineární kombinace dvou základních (bázových) čísel, které většinou označujeme symboly 1 a i a nazýváme je jednotkami: 1 je reálná jednotka, i je jednotka imaginární. Tyto dvě číselné hodnoty mají jednotkovou délku a jsou na sebe při zobrazení v rovině (nazývané rovina komplexní) kolmé, přičemž je stanoveno speciální pravidlo pro umocnění jednotky i:

i2=-1

Množinu všech komplexních čísel tedy můžeme zapsat ve tvaru výše zmiňované lineární kombinace:

C={a+bi: i2=-1}

(jednotku 1 není zapotřebí zapisovat, protože vždy platí 1a=a=a1 pro jakékoli a). Hodnotu a nazýváme reálná složka komplexního čísla, hodnotu b složka imaginární. Aditivní operace (součet, rozdíl) se v komplexní rovině provádí stejným způsobem, jako v každém jiném vektorovém prostoru, tj. složku po složce: výsledná reálná složka je vypočtena součtem obou reálných složek, stejný výpočet se provede i pro složku imaginární. Rozdíl nastává při násobení dvou komplexních čísel, protože musíme vědět, jaký výsledek vznikne při násobení dvou jednotek. Pomůže nám jednoduchá tabulka:

Multiplikativní operace Výsledek
1×1 1
1×i i
i×1 i
i×i –1

Všechny algebraické operace s komplexními čísly zachovávají asociativitu i komutativitu. Pro každé komplexní číslo z různé od nuly existuje i inverzní prvek z' takový, že platí vztah zz'=1. Množina komplexních čísel spolu s operacemi + a × tvoří algebraickou strukturu komutativní těleso. Současně můžeme vyjádřit i velikost každého komplexního čísla: |z|=(a2+b2)1/2, množina komplexních čísel tedy tvoří metrický prostor. Čtyři základní aditivní a multiplikativní operace prováděné nad komplexními čísly je možné zapsat následujícím způsobem (u operace dělení se výpočet musel uspořádat tak, aby pod zlomkovou čarou byla pouze reálná hodnota):

(u+iv) + (x+iy) = (u+x) + i(v+y)
(u+iv) - (x+iy) = (u-x) + i(v-y)
(u+iv) * (x+iy) = (ux - vy) + i(vx + uy)
(u+iv) / (x+iy) = ((ux + vy) + i(vx - uy)) / (x^2 + y^2)

Pomocí komplexních čísel je možné popsat jakýkoli bod v rovině. Podobným způsobem lze vyjádřit číselnou hodnotu ve čtyřrozměrném (hyperkomplexním) prostoru. Zajímavé přitom je, že zatímco pro komplexní čísla jsou zachovány vlastnosti komutativního tělesa jako je asociativita, komutativita, existence inverzního prvku apod., ve čtyřrozměrném prostoru je vždy alespoň jedna z těchto vlastností porušena (nesplněna). V následujícím textu si popíšeme jednu možnost cestu z komplexní roviny do 4D prostoru (druhou cestou je použití hyperkomplexních čísel).

Kvaterniony (quaternions) a kvaternionovou algebru vymyslel v roce 1843 známý matematik William Rowan Hamilton, který původně hledal rozšíření komplexních čísel z 2D plochy do 3D prostoru. Takové rozšíření však není možné vytvořit, nejbližší ekvivalent komplexních čísel jsou až čtyřrozměrné struktury. Hamilton provedl revoluční krok v tom, že jím vymyšlené kvaterniony nesplňovaly vlastnost do té doby považovanou za samozřejmost – komutativitu. Později se objevily i další užitečné struktury, které komutativitu nesplňují, například matice. Matematici s oblibou vypráví historku, že Hamiltona základní vztahy kvaternionové algebry napadly, když na procházce se svou manželkou procházel pod mostem Broom Bridge; na onom mostě se dnes nachází kamenná deska s připomínkou této události. Broom Bridge je v současnosti místem častého setkání matematiků.

fractals62_7

Obrázek 5: Most s pamětní deskou objasňující historii vzniku kvaternionů

fractals62_8

Obrázek 6: Detail pamětní desky, dnes již dokonce „ozdobené“ barevnou čmouhou

Kvaterniony jsou obdobou komplexních čísel, ovšem s tím rozdílem, že mají čtyři na sebe kolmé jednotky, které označujeme symboly 1, i, j a k. Jednotka 1 se někdy nazývá skalární složkou, zbylé tři jednotky i, j, k pak složkami vektorovými (to souvisí s využitím kvaternionů při popisu rotací). Každý kvaternion lze popsat lineární kombinací všech čtyř jednotek: q=x+yi+zj+wk. Pro vzájemné násobení těchto jednotek platí následující vztahy:

Multiplikativní operace Výsledek
1×1 1
1×i i
1×j j
1×k k
i×1 i
j×1 j
k×1 k
i×j k
j×i -k
j×k i
k×j -i
k×i j
i×k -j
i×i=j×j=k×k –1
i×j×k –1

Všimněte si, že při násobení není obecně zachována komutativita operací, tj. například výsledek operace jk se nerovná výsledku operace kj. To znamená, že kvaterniony netvoří algebraickou strukturu komutativní těleso a při násobení dvou kvaternionů si musíme dát pozor na pořadí operací (ostatně podobně jako při násobení matic). Násobení jedničkou (skalární složkou, 1) zachovává hodnotu druhého prvku, podobně jako je tomu u reálných i komplexních čísel. Kvaterniony tvoří největší algebraické nadtěleso množiny reálných čísel (i komplexní čísla jsou nadtělesem reálných čísel).

Pokud máme dva kvaterniony:

q1=x1+y1i+z1j+w1k
a
q2=x2+y2i+z2j+w2k

je možné jejich vzájemné vynásobení provést podle následujícího schématu:

q1q2=
1(x1x2 – y1y2 – z1z2 – w1w2) +
i(y1x2 + x1y2 + w1z2 – z1w2) +
j(z1x2 – w1y2 + x1z2 + y1w2) +
k(w1x2 + z1y2 – y1z2 + x1w2

10. Kvaterniony v programovacím jazyku Kawa

Podívejme se nyní na použití kvaternionů v jazyku Kawa. Kvaternion lze zapsat přímo svou hodnotou:

#|kawa:6|# 1+2i+3j+4k
1+2i+3j+4k

Nebo lze použít konstruktor make-rectangular:

#|kawa:7|# (make-rectangular 1 2 3 4)
1+2i+3j+4k
 
#|kawa:8|# (make-rectangular 1 0 0 0)
1

Základní aritmetické operace s kvaterniony:

#|kawa:9|# (define one 1+0i+0j+0k)
#|kawa:10|# (* one one)
1
 
#|kawa:15|# (define imag 0+1i+0j+0k)
#|kawa:16|# (* imag imag)
-1
 
#|kawa:17|# (define other 0+1i+2j+3k)
#|kawa:18|# (* other other)
-14
 
#|kawa:19|# (* other imag)
-1+3j-2k

Definována je i operace dělení:

#|kawa:23|# (/ imag other)
1/14+3/14j-1/7k

Další operace – velikost (absolutní hodnota):

#|kawa:24|# (magnitude imag)
1.0
 
#|kawa:25|# (magnitude other)
3.7416573867739413

Úhel (jen plošný):

#|kawa:29|# (angle 1)
0.0
 
#|kawa:28|# (angle imag)
1.5707963267948966
 
#|kawa:27|# (angle other)
1.5707963267948966

11. Jednotky u numerických hodnot

Mezi velmi zajímavou a potenciálně i užitečnou vlastnost programovacího jazyka Kawa patří možnost přiřadit libovolné číselné hodnotě i její jednotku. Jednotka je k číselné hodnotě přiřazena v čase běhu aplikace a zúčastní se i operací prováděných s danou hodnotou (součet, součin, rozdíl, podíl). Můžeme tak například používat konstanty s přiřazenými jednotkami:

1A
0.5V
32cm
120s

Nebo též z běžné hodnoty:

(make-quantity 10 "cm")
10cm
 
(make-quantity 10 unit:cm)
10cm
Poznámka: dané jednotky ovšem musí být nejdříve definovány – viz další text.

Pochopitelně lze vytvořit i proměnné a inicializovat je hodnotou i s uvedením jednotky:

(define MAX_CURRENT 1A)
(define AVERAGE_DISTANCE 32cm)
(define TIMEOUT 120s)

Je však možné použít libovolnou jednotku? Resp. přesněji řečeno, kontroluje se, zda je uvedená jednotka známá a nedopustíme se například omylem přepisu, jako v následujícím příkladu?

(define AVERAGE_DISTANCE 32cn)

Jednotky (jejich identifikátory) se skutečně kontrolují. Přímo v základních knihovnách programovacího jazyka Kawa jsou některé jednotky definovány, další je možné definovat podle toho, jaký konkrétní problém vyvíjená aplikace řeší. Definice nové jednotky může vypadat následovně:

(define-base-unit meter "distance")
(define-unit stadion 176meter)

Vytvořili jsme jednotku „metr“ a „stadion“, který měří přibližně 176 metrů.

S novou jednotkou můžeme provést například součin s konstantou:

(* 2stadion 3)
6.0stadion

12. Použití jednotek v praxi při aritmetických operacích

To však není vše – jazyk Kawa do určité míry dokáže odvodit i jednotku výsledku nějaké operace. U součtu a rozdílu je to jednoduché, ovšem podobně se odvozuje i jednotka při násobení a dělení:

(* 10cm 2)
20.0cm
 
(* 10cm 10)
100.0cm
 
(* 10cm 10cm)
100.0cm^2
 

Dělení hodnot s různými jednotkami:

(/ 10s 5cm)
2.0s*cm^-1
 
(/ 5cm 10s)
0.5cm*s^-1
Poznámka: toto je skutečně velmi užitečná vlastnost, která nám pomůže odhalit mnohé chyby v algoritmu. Na konci výpočtu se totiž můžeme přesvědčit i o jednotce výsledku a zjistit tak, že se neprovádí „podivné“ operace, které například ani nemají obdobu v reálném světě. Ostatně můžeme si uvést příklad:
(define-base-unit A "electric current")
3A
3.0A
 
(define-base-unit V "voltage")
5V
5.0V
 
(* 3A 5V)
15.0A*V
 
(define power (* 3A 5V))
(define resistance (/ 5V 3A))
power
15.0A*V
 
resistance
1.6666666666666667V*A^-1
 
(define wrong-power (* 3A 5cm))
wrong-power
15.0A*cm
 

13. Líné vyhodnocování výrazů

Zmínit se musíme i o takzvaném líném vyhodnocování výrazů, což je vlastnost, se kterou jsme se seznámili při popisu programovacího jazyka Clojure. V Kawě je možné nechat nějaký výraz „líně“ vyhodnotit pomocí speciální formy delay. Výsledkem je objekt, který reprezentuje budoucí hodnotu. Pokud hodnotu budeme skutečně potřebovat použít, stačí ji buď vyhodnotit nebo si výpočet vynutit funkcí force.

Podívejme se nyní na příklad (získaný přímo z dokumentace), v němž je implementován generátor všech celých kladných čísel:

(define integers
  (letrec ((next
            (lambda (n)
              (cons n (delay (next (+ n 1)))))))
    (next 0)))

Generování je pochopitelně „líné“, tj. hodnota (následující hodnota v řadě celých čísel) se vyhodnotí až ve chvíli, kdy je to zapotřebí:

#|kawa:10|# (car integers)
0
 
#|kawa:11|# (cadr integers)
1

Některé další příklady líného vyhodnocení, včetně spuštění výpočtu v samostatném vlákně, si ukážeme příště.

14. Rozhraní mezi jazyky Java a Kawa

Poslední vlastností programovacího jazyka Kawa, kterou se dnes budeme zabývat, je takzvaná interoperabilita (zkráceně interop) mezi programovacími jazyky Java a Kawa. Dnes si ukážeme základní příklady ukazující interoperabilitu ve směru Kawa→Java, tedy použití tříd z Javy ve skriptech, které jsou vytvořeny v programovacím jazyku Kawa. Nejprve se podívejme, jak se může zavolat statická metoda z nějaké třídy. Je to snadné:

#|kawa:35|# (java.lang.Math:abs -10)
10.0

Konstrukce objektu:

#|kawa:37|# (java.awt.Rectangle 10 20 30 40)
java.awt.Rectangle[x=10,y=20,width=30,height=40]

Vytvoření kolekce:

#|kawa:1|# (java.util.ArrayList 11 22 33)
#(11 22 33)

Další využití konstruktoru, tentokrát při konstrukci množiny:

#|kawa:2|# (java.util.TreeSet 2 4 6 8 1 3 5 7)
[1, 2, 3, 4, 5, 6, 7, 8]

Pokud je nějaký Javovský objekt vytvořen, můžeme volat jeho metody, a to s použitím „dvojtečkové notace“, nikoli běžnější „tečkove notace“, která ve Scheme slouží k dalším účelům:

#|kawa:5|# (define frame (javax.swing.JFrame "foobar"))
#|kawa:6|# (frame:setVisible #t)

Přístup k atributům třídy:

java.lang.Integer:MAX_VALUE
2147483647

Konstrukce polí (v Javě typovaných):

(int[] 4 5 6)
[4 5 6]

Automatická konverze hodnot při konstrukci pole:

(float[] 1/2 1/3 1/4)
[0.5 0.33333334 0.25]

Konstrukce objektu a volání jeho metod:

(define r (java.util.Random))
(r:nextInt)
666226103

Vytvoření zlomku s náhodnou hodnotou:

(inexact->exact (r:nextFloat))
5864237/16777216

15. Obsah následující části seriálu

V následující části tohoto seriálu dokončíme popis ostatních vlastností interpretru a překladače Kawa. Kromě podrobnějšího popisu rozhraní vytvořeného mezi programovacími jazyky Java a Scheme si taktéž ukážeme, jakým způsobem se provádí překlad programu vytvořeného v Clojure do bajtkódu JVM. Nezapomeneme ani na popis toho, jak se projeví (nepovinné) typové informace u parametrů funkcí na kvalitě a rychlosti provádění (dnes pochopitelně především JITování) výsledného bajtkódu.

16. Krátké shrnutí: seznam implementací jazyka Scheme, LISP a Clojure

V tabulkách zobrazených pod tímto odstavcem naleznete seznam implementací jazyka Scheme, LISP a Clojure, kterými jsme se již zabývali nebo kterými se budeme zabývat:

# Implementace jazyka Scheme
1 GNU Guile
2 TinyScheme
3 Kawa
4 Chicken
5 Racket
6 Gambit
7 Chez
8 MIT/GNU
9 Scheme48
10 Bigloo
# Implementace dialektu jazyka LISP
1 Common LISP
2 Emacs LISP
3 PicoLisp
4 AutoLISP
# Implementace LISPovského jazyka
1 Clojure
2 ClojureScript
3 Pixie [1] [2]
4 Wisp [1] [2]
5 Hy [1] [2]
6 Clojure-py
7 Script-fu [1] [2] [3] [4]

17. Programovací jazyky pro JVM aneb zdaleka nejde jen o Javu

Virtuální stroj Javy (JVM), specifikace JVM a dokonce ani jeho instrukční soubor vlastně nikde striktně nepředpokládají, že JVM bude spouštět pouze bajtkód získaný překladem javovských programů. Ve specifikaci JVM je dokonce na několika místech explicitně zmíněn předpoklad, že nad virtuálním strojem Javy budou provozovány i další programovací jazyky umožňující přímý či nepřímý překlad do bajtkódu. Kromě toho je samozřejmě možné přímo v Javě vytvořit interpret prakticky libovolného (interpretovaného) programovacího jazyka, takže vlastně nebude velkým překvapením, když zjistíme, že dnes těchto „JVM jazyků“ již existuje relativně velké množství. V následující tabulce jsou vypsány ty nejznámější a pravděpodobně nejpoužívanější jazyky, a to pro úplnost včetně samotné Javy:

Jazyk pro JVM Stručný popis Odkaz
Java primární jazyk pro JVM, bajtkód odpovídá právě Javě https://www.oracle.com/ja­va/index.html
Clojure moderní dialekt programovacího jazyka Lisp https://clojure.org/
Groovy dynamicky typovaný jazyk pro JVM http://groovy-lang.org/
Rhino jedna z implementací JavaScriptu https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino
Nashorn alternativní implementace JavaScriptu https://blogs.oracle.com/nashorn/
JRuby portace jazyka Ruby na JVM http://jruby.org/
Jython portace jazyka Python na JVM http://www.jython.org/
Kotlin moderní staticky typovaný jazyk http://kotlinlang.org/
Scala další moderní jazyk pro JVM https://www.scala-lang.org/

Obrázek 7: Logo programovacího jazyka Jython.

Scala

Pravděpodobně nejznámějším příkladem programovacího jazyka provozovaného nad JVM je Scala, která nabízí prakticky bezproblémovou spolupráci mezi částmi kódu psanými ve Scale a zbytkem aplikace psaným v Javě (popř. jsou některé projekty psané pouze ve Scale, ovšem provozovány jsou například na ryze javovských serverech – Tomcat, Jetty atd.). Díky tomu, že zdrojové kódy psané ve Scale jsou přímo překládány do bajtkódu, získali tvůrci tohoto programovacího jazyka prakticky zadarmo veškeré vymoženosti, které virtuální stroj Javy (či přesněji řečeno celé JRE) poskytuje – od poměrně pečlivé kontroly bajtkódu při jeho načítání do virtuálního stroje přes použití správců paměti a JIT překladačů (Just in Time Compiler) až po možnost využití rozsáhlých standardních knihoven J2SE a samozřejmě taktéž mnoha dalších knihoven a frameworků, které jsou pro JVM dostupné. Ovšem Scala samozřejmě není jediným programovacím jazykem, který díky překladu do bajtkódu umožňuje využít prakticky veškerého potenciálu JVM/JRE.

Obrázek 8: Logo programovacího jazyka Scala.

Clojure

Z dalších překladačů programovacích jazyků, které pro virtuální stroj Javy vznikly, je podle mého názoru nejzajímavějším jazykem a současně i jazykem s velkým potenciálem pro budoucnost programovací jazyk s názvem Clojure, jehož autorem a dodnes nejaktivnějším vývojářem a propagátorem je Rich Hickey. Samotný název tohoto jazyka vznikl vložením písmene „j“ (Java/JVM) do slova closure (toto slovo se používá ve smyslu „lexikální uzávěr“ – důležitá abstrakce používaná nejenom ve funkcionálních programovacích jazycích). Velká část předností a pro mnohé vývojáře taktéž záporů programovacího jazyka Clojure vychází z toho, že se jedná o programovací jazyk, jehož syntaxe a sémantika do značné míry vychází z LISPu a Scheme, tedy jazyků známých především tím, že se v programech v nich psaných používá nadměrné množství kulatých závorek. Podrobnější informace o Clojure byly uvedeny v samostatném seriálu, který již vyšel na serveru www.root.cz.

Obrázek 9: Logo programovacího jazyka Clojure.

Groovy

Dalším programovacím jazykem, a nutno říci že jazykem poměrně populárním, je Groovy. Jedná se o jazyk inspirovaný některými dalšími (většinou dynamicky typovanými) programovacími jazyky, jako je Python, Ruby, ale například i Perl. Groovy podporuje objektově orientované programování a oproti Javě umožňuje psát kratší kód, z něhož jsou odstraněny méně podstatné části, které Java jakožto silně staticky typovaný jazyk vyžaduje. Z tohoto důvodu se Groovy velmi často používá všude tam, kde je vyžadovaný skriptovací jazyk běžící nad JVM. Dobrým příkladem je například konzole Jenkinsu, která ve výchozím nastavení používá právě Groovy. Podpora pro tento jazyk je součástí mnoha populárních integrovaných vývojových prostředí, a to včetně IntelliJ IDEA, Netbeans i Eclipse (přes pluginy – doplňkové moduly).

Obrázek 10: Logo programovacího jazyka Groovy.

JRuby, Jython, Rhino a Nashhorn

Zatímco Scala, ClojureGroovy jsou novými jazyky, které původně vznikly přímo a pouze pro potřeby programátorů používajících virtuální stroj Javy (JVM), zmíníme se v této podkapitole alespoň ve stručnosti o jazycích „klasických“, které byly na JVM pouze naportovány. V první řadě se jedná o projekty pojmenované JRuby a Jython, což jsou varianty jazyků Ruby a Python. Původní interpretry Ruby a Pythonu jsou naprogramovány v jazyku C (proto se ostatně tato varianta Pythonu nazývá CPython), JRuby a Jython jsou reimplementace pro JVM (navíc byl Python portován i na platformu .NET ve formě projektu IronPython a existuje i varianta Pythonu nazvaná PyPy naprogramovaná v samotném Pythonu, resp. přesněji řečeno v jeho zjednodušené variantě RPython). Na platformu JVM byl portován i programovací jazyk JavaScript, a to dokonce několikrát. Implementaci JavaScriptu zajišťují projekty Rhino a Nashhorn.

Obrázek 11: Logo programovacího jazyka JRuby.

Kotlin

Posledním programovacím jazykem určeným pro běh nad virtuálním strojem Javy, o němž se dnes alespoň ve stručnosti zmíníme, je jazyk pojmenovaný Kotlin. Jedná se o moderní staticky typovaný programovací jazyk vyvinutý ve společnosti JetBrains a jeho cíl je vlastně velmi podobný cíli, který si dal již zmíněný a poněkud starší jazyk Scala – efektivní a rychlá tvorba typově bezpečných aplikací určených pro běh nad JVM. Typovost jde ještě o krok dále, než je tomu v Javě, protože například rozlišuje mezi nulovatelnými a nenulovatelnými datovými typy. Na rozdíl od Scaly je však rychlost překladu zdrojových kódů naprogramovaných v Kotlinu rychlejší a blíží se rychlosti překladu kódů napsaných v samotné Javě. Kotlin podporuje různá paradigmata: objektově orientované, procedurální i funkcionální. Tomuto velmi zajímavému programovacímu jazyku se budeme věnovat v samostatném seriálu.

Obrázek 12: Logo programovacího jazyka Kotlin.

Další programovací jazyky portované na JVM

Na virtuální stroj Javy bylo portováno i mnoho dalších programovacích jazyků, ať již se jednalo o překladače či o interpretry. V následující tabulce jsou některé z těchto jazyků vypsány. V prvním sloupci je zobrazen název původního jazyka popř. rodiny jazyků, ve sloupci druhém pak jméno jeho konkrétní implementace pro JVM. Povšimněte si, že některé jazyky byly portovány několikrát (to se ostatně týkalo již výše zmíněného JavaScriptu):

Jazyk Implementace pro JVM
Ada JGNAT
Arden Syntax Arden2ByteCode
COBOL Micro Focus Visual COBOL
ColdFusion Markup Language (CFML) Adobe ColdFusion
ColdFusion Markup Language (CFML) Railo
ColdFusion Markup Language (CFML) Lucee
ColdFusion Markup Language (CFML) Open BlueDragon
Common Lisp Armed Bear Common Lisp
Cypher Neo4j
Mercury Mercury (Java grade)
Pascal MIDletPascal
Pascal Oxygene
Perl 6 Rakudo Perl 6
PHP Quercus
Prolog JIProlog
Prolog TuProlog
R Renjin
Rexx NetRexx
Ruby JRuby
Ruby Mirah
Scheme Bigloo
Scheme Kawa
Scheme SISC
Scheme JScheme
Tcl Jacl
Visual Basic Jabaco

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 closure1.scm uzávěry, příklad 1 https://github.com/tisnik/lisp-families/blob/master/kawa/clo­sure1.scm
2 closure2.scm uzávěry, příklad 2 https://github.com/tisnik/lisp-families/blob/master/kawa/clo­sure2.scm
3 closure3.scm uzávěry, příklad 3 https://github.com/tisnik/lisp-families/blob/master/kawa/clo­sure3.scm
4 closure4.scm uzávěry, příklad 4 https://github.com/tisnik/lisp-families/blob/master/kawa/clo­sure4.scm
5 cons.scm funkce cons https://github.com/tisnik/lisp-families/blob/master/kawa/cons.scm
6 dot_pairs.scm konstrukce tečka dvojic https://github.com/tisnik/lisp-families/blob/master/kawa/dot_pa­irs.scm
7 factorial1.scm rekurzivní výpočet faktoriálu, první varianta https://github.com/tisnik/lisp-families/blob/master/kawa/fac­torial1.scm
8 factorial2.scm rekurzivní výpočet faktoriálu, druhá varianta https://github.com/tisnik/lisp-families/blob/master/kawa/fac­torial2.scm
9 factorial3.scm tail rekurze při výpočtu faktoriálu https://github.com/tisnik/lisp-families/blob/master/kawa/fac­torial3.scm
10 functions.scm deklarace a volání funkcí https://github.com/tisnik/lisp-families/blob/master/kawa/fun­ctions.scm
11 integer_generator.scm generátor sekvence celých kladných čísel https://github.com/tisnik/lisp-families/blob/master/kawa/in­teger_generator.scm
12 lexical_scope1.scm lexikální oblast platnosti proměnných, příklad 1 https://github.com/tisnik/lisp-families/blob/master/kawa/le­xical_scope1.scm
13 lexical_scope2.scm exikální oblast platnosti proměnných, příklad 2 https://github.com/tisnik/lisp-families/blob/master/kawa/le­xical_scope2.scm
14 lexical_scope3.scm lexikální oblast platnosti proměnných, příklad 3 https://github.com/tisnik/lisp-families/blob/master/kawa/le­xical_scope3.scm
15 lexical_scope4.scm lexikální oblast platnosti proměnných, příklad 4 https://github.com/tisnik/lisp-families/blob/master/kawa/le­xical_scope4.scm
16 lists.scm práce se seznamy https://github.com/tisnik/lisp-families/blob/master/kawa/lists.scm
17 nested_loops1.scm vnořené smyčky do https://github.com/tisnik/lisp-families/blob/master/kawa/nes­ted_loops1.scm
18 nested_loops2.scm vnořené smyčky do https://github.com/tisnik/lisp-families/blob/master/kawa/nes­ted_loops2.scm
19 pi1.scm výpočet Pi Wallisovým součinem https://github.com/tisnik/lisp-families/blob/master/kawa/pi1.scm
20 pi2.scm výpočet Pi Wallisovým součinem řadou, použití zlomků https://github.com/tisnik/lisp-families/blob/master/kawa/pi2.scm
21 pi3.scm výpočet Pi Wallisovým součinem řadou, převod na reálná čísla https://github.com/tisnik/lisp-families/blob/master/kawa/pi3.scm
22 quantities.scm použití jednotek při výpočtech https://github.com/tisnik/lisp-families/blob/master/kawa/qu­antities.scm
23 quaternions.scm použití kvaternionů https://github.com/tisnik/lisp-families/blob/master/kawa/qu­aternions.scm

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

20. Odkazy na Internetu

  1. Kawa: Compiling Scheme to Java
    https://www.mit.edu/afs.new/sip­b/project/kawa/doc/kawa-tour.html
  2. Kawa in Languages shootout
    http://per.bothner.com/blog/2010/Kawa-in-shootout/
  3. Kawa 2.0 Supports Scheme R7RS
    https://developers.slashdot­.org/story/14/12/13/2259225/ka­wa-20-supports-scheme-r7rs/
  4. Kawa — fast scripting on the Java platform
    https://lwn.net/Articles/623349/
  5. SLIME (Wikipedia)
    http://en.wikipedia.org/wiki/SLIME
  6. slime.vim
    http://s3.amazonaws.com/mps/slime.vim
  7. What are the best scheme implementations?
    https://www.slant.co/topic­s/5282/~scheme-implementations
  8. Bigloo homepage
    http://www-sop.inria.fr/mimosa/fp/Bigloo/
  9. FTP s tarbally Bigloo
    ftp://ftp-sop.inria.fr/indes/fp/Bigloo
  10. GOTO 2018 • Functional Programming in 40 Minutes • Russ Olsen
    https://www.youtube.com/wat­ch?v=0if71HOyVjY
  11. TinyScheme (stránka na Sourceforge)
    http://tinyscheme.sourcefor­ge.net/home.html
  12. Embedding Tiny Scheme in a Game
    http://www.silicondelight­.com/embedding-tiny-scheme-in-a-game/
  13. Embedding Scheme for a game mission scripting DSL
    http://carloscarrasco.com/embedding-scheme-for-a-game-mission-scripting-dsl.html
  14. Všechny verze TinyScheme na SourceForge
    https://sourceforge.net/pro­jects/tinyscheme/files/ti­nyscheme/
  15. Fork TinyScheme na GitHubu
    https://github.com/yawnt/tinyscheme
  16. Ackermannova funkce
    https://cs.wikipedia.org/wi­ki/Ackermannova_funkce
  17. Ackermann function na Rosetta Code
    https://rosettacode.org/wi­ki/Ackermann_function#Sche­me
  18. Success Stories (lisp.org)
    https://lisp-lang.org/success/
  19. Allegro Common Lisp Success Stories
    https://franz.com/success/
  20. Clojure Success Stories
    https://clojure.org/commu­nity/success_stories
  21. Scheme Quick Reference
    https://www.st.cs.uni-saarland.de/edu/config-ss04/scheme-quickref.pdf
  22. Slajdy o Scheme (od slajdu číslo 15)
    https://docs.google.com/pre­sentation/d/1abmDnKjrq1tcjGvvRNAK­hOiSTSE2lyagtcEPal07Gbo/e­dit
  23. Scheme Cheat Sheet
    https://github.com/smythp/scheme-cheat-sheet
  24. Embedding Lua, embedding Guile
    http://puntoblogspot.blog­spot.com/2013/04/embedding-lua-embedding-guile.html
  25. Lambda Papers
    https://en.wikisource.org/wi­ki/Lambda_Papers
  26. Revised7Report on the Algorithmic Language Scheme
    https://small.r7rs.org/at­tachment/r7rs.pdf
  27. 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/
  28. Why is Scheme my first language in university?
    https://softwareengineerin­g.stackexchange.com/questi­ons/115252/why-is-scheme-my-first-language-in-university
  29. The Perils of JavaSchools
    https://www.joelonsoftware­.com/2005/12/29/the-perils-of-javaschools-2/
  30. How to Design Programs, Second Edition
    https://htdp.org/2019–02–24/index.html
  31. LilyPond
    http://lilypond.org/
  32. LilyPond — Extending (přes Scheme)
    http://lilypond.org/doc/v2­.18/Documentation/extendin­g/scheme-tutorial
  33. Scheme in LilyPond
    http://lilypond.org/doc/v2­.18/Documentation/extendin­g/scheme-in-lilypond
  34. GnuCash
    http://www.gnucash.org/
  35. Custom Reports (in GNU Cash)
    https://wiki.gnucash.org/wi­ki/Custom_Reports
  36. Program by Design
    https://programbydesign.org/
  37. SchemePy
    https://pypi.org/project/SchemePy/
  38. 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
  39. femtolisp
    https://github.com/JeffBe­zanson/femtolisp
  40. (How to Write a (Lisp) Interpreter (in Python))
    http://norvig.com/lispy.html
  41. Repositář s Guile Emacsem
    http://git.hcoop.net/?p=bpt/guile.git
  42. Interacting with Guile Compound Data Types in C
    http://www.lonelycactus.com/gu­ilebook/x1555.html
  43. Calling Guile functions from C
    http://www.lonelycactus.com/gu­ilebook/c1204.html#SECCAL­LGUILEFUNC
  44. Arrays, and other compound data types
    http://www.lonelycactus.com/gu­ilebook/charrays.html
  45. Interacting with Guile Compound Data Types in C
    http://www.lonelycactus.com/gu­ilebook/x1555.html
  46. Guile Reference Manual
    https://www.gnu.org/softwa­re/guile/manual/html_node/in­dex.html
  47. Scheme: Summary of Common Syntax
    https://www.gnu.org/softwa­re/guile/manual/html_node/Syn­tax-Summary.html#Syntax-Summary
  48. Scripting with Guile: Extension language enhances C and Scheme
    https://www.ibm.com/develo­perworks/library/l-guile/index.html
  49. Having fun with Guile: a tutorial
    http://dustycloud.org/misc/guile-tutorial.html
  50. Guile: Loading Readline Support
    https://www.gnu.org/softwa­re/guile/manual/html_node/Lo­ading-Readline-Support.html#Loading-Readline-Support
  51. lispy
    https://pypi.org/project/lispy/
  52. Lython
    https://pypi.org/project/Lython/
  53. Lizpop
    https://pypi.org/project/lizpop/
  54. Budoucnost programovacích jazyků
    http://www.knesl.com/budoucnost-programovacich-jazyku
  55. LISP Prolog and Evolution
    http://blog.samibadawi.com/2013/05/lisp-prolog-and-evolution.html
  56. List of Lisp-family programming languages
    https://en.wikipedia.org/wi­ki/List_of_Lisp-family_programming_languages
  57. clojure_py na indexu PyPi
    https://pypi.python.org/py­pi/clojure_py
  58. PyClojure
    https://github.com/eigenhom­bre/PyClojure
  59. Hy na GitHubu
    https://github.com/hylang/hy
  60. Hy: The survival guide
    https://notes.pault.ag/hy-survival-guide/
  61. Hy běžící na monitoru terminálu společnosti Symbolics
    http://try-hy.appspot.com/
  62. Welcome to Hy’s documentation!
    http://docs.hylang.org/en/stable/
  63. Hy na PyPi
    https://pypi.org/project/hy/#des­cription
  64. Getting Hy on Python
    https://lwn.net/Articles/596626/
  65. Programming Can Be Fun with Hy
    https://opensourceforu.com/2014/02/pro­gramming-can-fun-hy/
  66. Přednáška o projektu Hy (pětiminutový lighttalk)
    http://blog.pault.ag/day/2013/04/02
  67. Hy (Wikipedia)
    https://en.wikipedia.org/wiki/Hy
  68. GNU Emacs Lisp Reference Manual: Point
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Point.html
  69. GNU Emacs Lisp Reference Manual: Narrowing
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Narrowing.html
  70. GNU Emacs Lisp Reference Manual: Functions that Create Markers
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Creating-Markers.html
  71. GNU Emacs Lisp Reference Manual: Motion
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Motion.html#Motion
  72. GNU Emacs Lisp Reference Manual: Basic Char Syntax
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Basic-Char-Syntax.html
  73. Elisp: Sequence: List, Array
    http://ergoemacs.org/emac­s/elisp_list_vs_vector.html
  74. Elisp: Property List
    http://ergoemacs.org/emac­s/elisp_property_list.html
  75. Elisp: Hash Table
    http://ergoemacs.org/emac­s/elisp_hash_table.html
  76. Elisp: Association List
    http://ergoemacs.org/emac­s/elisp_association_list.html
  77. The mapcar Function (An Introduction to Programming in Emacs Lisp)
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­intr/mapcar.html
  78. Anaphoric macro
    https://en.wikipedia.org/wi­ki/Anaphoric_macro
  79. Some Common Lisp Loop Macro Examples
    https://www.youtube.com/wat­ch?v=3yl8o6r_omw
  80. A Guided Tour of Emacs
    https://www.gnu.org/softwa­re/emacs/tour/
  81. The Roots of Lisp
    http://www.paulgraham.com/ro­otsoflisp.html
  82. Evil (Emacs Wiki)
    https://www.emacswiki.org/emacs/Evil
  83. Evil (na GitHubu)
    https://github.com/emacs-evil/evil
  84. Evil (na stránkách repositáře MELPA)
    https://melpa.org/#/evil
  85. 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
  86. GNU Emacs (home page)
    https://www.gnu.org/software/emacs/
  87. GNU Emacs (texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?GnuEmacs
  88. An Introduction To Using GDB Under Emacs
    http://tedlab.mit.edu/~dr/gdbin­tro.html
  89. An Introduction to Programming in Emacs Lisp
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­intr/index.html
  90. 27.6 Running Debuggers Under Emacs
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­macs/Debuggers.html
  91. GdbMode
    http://www.emacswiki.org/e­macs/GdbMode
  92. Emacs (Wikipedia)
    https://en.wikipedia.org/wiki/Emacs
  93. Emacs timeline
    http://www.jwz.org/doc/emacs-timeline.html
  94. Emacs Text Editors Family
    http://texteditors.org/cgi-bin/wiki.pl?EmacsFamily
  95. Vrapper aneb spojení možností Vimu a Eclipse
    https://mojefedora.cz/vrapper-aneb-spojeni-moznosti-vimu-a-eclipse/
  96. 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/
  97. Emacs/Evil-mode – A basic reference to using evil mode in Emacs
    http://www.aakarshnair.com/posts/emacs-evil-mode-cheatsheet
  98. From Vim to Emacs+Evil chaotic migration guide
    https://juanjoalvarez.net/es/de­tail/2014/sep/19/vim-emacsevil-chaotic-migration-guide/
  99. Introduction to evil-mode {video)
    https://www.youtube.com/wat­ch?v=PeVQwYUxYEg
  100. EINE (Emacs Wiki)
    http://www.emacswiki.org/emacs/EINE
  101. EINE (Texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?EINE
  102. ZWEI (Emacs Wiki)
    http://www.emacswiki.org/emacs/ZWEI
  103. ZWEI (Texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?ZWEI
  104. Zmacs (Wikipedia)
    https://en.wikipedia.org/wiki/Zmacs
  105. Zmacs (Texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?Zmacs
  106. TecoEmacs (Emacs Wiki)
    http://www.emacswiki.org/e­macs/TecoEmacs
  107. Micro Emacs
    http://www.emacswiki.org/e­macs/MicroEmacs
  108. Micro Emacs (Wikipedia)
    https://en.wikipedia.org/wi­ki/MicroEMACS
  109. EmacsHistory
    http://www.emacswiki.org/e­macs/EmacsHistory
  110. Seznam editorů s ovládáním podobným Emacsu či kompatibilních s příkazy Emacsu
    http://www.finseth.com/emacs.html
  111. evil-numbers
    https://github.com/cofi/evil-numbers
  112. Debuggery a jejich nadstavby v Linuxu (1.část)
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu/
  113. Debuggery a jejich nadstavby v Linuxu (2.část)
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-2-cast/
  114. Debuggery a jejich nadstavby v Linuxu (3): Nemiver
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-3-nemiver/
  115. Debuggery a jejich nadstavby v Linuxu (4): KDbg
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-4-kdbg/
  116. 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/
  117. Org mode
    https://orgmode.org/
  118. The Org Manual
    https://orgmode.org/manual/index.html
  119. Kakoune (modální textový editor)
    http://kakoune.org/
  120. Vim-style keybinding in Emacs/Evil-mode
    https://gist.github.com/tro­yp/6b4c9e1c8670200c04c16036805773d8
  121. Emacs – jak začít
    http://www.abclinuxu.cz/clan­ky/navody/emacs-jak-zacit
  122. Programovací jazyk LISP a LISP machines
    https://www.root.cz/clanky/pro­gramovaci-jazyk-lisp-a-lisp-machines/
  123. Evil-surround
    https://github.com/emacs-evil/evil-surround
  124. Spacemacs
    http://spacemacs.org/
  125. Lisp: Common Lisp, Racket, Clojure, Emacs Lisp
    http://hyperpolyglot.org/lisp
  126. Common Lisp, Scheme, Clojure, And Elisp Compared
    http://irreal.org/blog/?p=725
  127. Does Elisp Suck?
    http://irreal.org/blog/?p=675
  128. Emacs pro mírně pokročilé (9): Elisp
    https://www.root.cz/clanky/emacs-elisp/
  129. 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/
  130. Clojure(Script) Interactive Development Environment that Rocks!
    https://github.com/clojure-emacs/cider
  131. An Introduction to Emacs Lisp
    https://harryrschwartz.com/2014/04/08/an-introduction-to-emacs-lisp.html
  132. Emergency Elisp
    http://steve-yegge.blogspot.com/2008/01/emergency-elisp.html
  133. Lambda calculus
    https://en.wikipedia.org/wi­ki/Lambda_calculus
  134. 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/
  135. Micro Manual LISP
    https://www.scribd.com/do­cument/54050141/Micro-Manual-LISP
  136. How Lisp Became God's Own Programming Language
    https://twobithistory.org/2018/10/14/lis­p.html
  137. History of Lisp
    http://jmc.stanford.edu/ar­ticles/lisp/lisp.pdf
  138. The Roots of Lisp
    http://languagelog.ldc.upen­n.edu/myl/llog/jmc.pdf
  139. Racket
    https://racket-lang.org/
  140. The Racket Manifesto
    http://felleisen.org/matthi­as/manifesto/
  141. MIT replaces Scheme with Python
    https://www.johndcook.com/blog/2009/03/26/mit-replaces-scheme-with-python/
  142. Adventures in Advanced Symbolic Programming
    http://groups.csail.mit.e­du/mac/users/gjs/6.945/
  143. Why MIT Switched from Scheme to Python (2009)
    https://news.ycombinator.com/i­tem?id=14167453
  144. Starodávná stránka XLispu
    http://www.xlisp.org/
  145. AutoLISP
    https://en.wikipedia.org/wi­ki/AutoLISP
  146. Seriál PicoLisp: minimalistický a výkonný interpret Lispu
    https://www.root.cz/serialy/picolisp-minimalisticky-a-vykonny-interpret-lispu/
  147. Common Lisp
    https://common-lisp.net/
  148. Getting Going with Common Lisp
    https://cliki.net/Getting%20Started
  149. Online Tutorial (Common Lisp)
    https://cliki.net/online%20tutorial
  150. Guile Emacs
    https://www.emacswiki.org/e­macs/GuileEmacs
  151. Guile Emacs History
    https://www.emacswiki.org/e­macs/GuileEmacsHistory
  152. Guile is a programming language
    https://www.gnu.org/software/guile/
  153. MIT Scheme
    http://groups.csail.mit.e­du/mac/projects/scheme/
  154. SIOD: Scheme in One Defun
    http://people.delphiforum­s.com/gjc//siod.html
  155. CommonLispForEmacs
    https://www.emacswiki.org/e­macs/CommonLispForEmacs
  156. Elisp: print, princ, prin1, format, message
    http://ergoemacs.org/emac­s/elisp_printing.html
  157. Special Forms in Lisp
    http://www.nhplace.com/ken­t/Papers/Special-Forms.html
  158. Basic Building Blocks in LISP
    https://www.tutorialspoin­t.com/lisp/lisp_basic_syn­tax.htm
  159. Introduction to LISP – University of Pittsburgh
    https://people.cs.pitt.edu/~mi­los/courses/cs2740/Lectures/Lis­pTutorial.pdf
  160. Why don't people use LISP
    https://forums.freebsd.org/threads/why-dont-people-use-lisp.24572/
  161. Structured program theorem
    https://en.wikipedia.org/wi­ki/Structured_program_the­orem
  162. Clojure: API Documentation
    https://clojure.org/api/api
  163. Tutorial for the Common Lisp Loop Macro
    http://www.ai.sri.com/pkarp/loop.html
  164. Common Lisp's Loop Macro Examples for Beginners
    http://www.unixuser.org/~e­uske/doc/cl/loop.html
  165. A modern list api for Emacs. No 'cl required.
    https://github.com/magnars/dash.el
  166. The LOOP Facility
    http://www.lispworks.com/do­cumentation/HyperSpec/Body/06_a­.htm
  167. Clojure.org: Vars and the Global Environment
    http://clojure.org/Vars
  168. Clojure.org: Refs and Transactions
    http://clojure.org/Refs
  169. Clojure.org: Atoms
    http://clojure.org/Atoms
  170. Clojure.org: Agents as Asynchronous Actions
    http://clojure.org/agents
  171. Transient Data Structureshttp://clojure.or­g/transients
  172. Dynamic Languages Strike Back
    http://steve-yegge.blogspot.cz/2008/05/dynamic-languages-strike-back.html
  173. Scripting: Higher Level Programming for the 21st Century
    http://www.tcl.tk/doc/scripting.html
  174. Clojure (na Wikipedia EN)
    http://en.wikipedia.org/wiki/Clojure
  175. Clojure (na Wikipedia CS)
    http://cs.wikipedia.org/wiki/Clojure
  176. SICP (The Structure and Interpretation of Computer Programs)
    http://mitpress.mit.edu/sicp/
  177. Pure function
    http://en.wikipedia.org/wi­ki/Pure_function
  178. Funkcionální programování
    http://cs.wikipedia.org/wi­ki/Funkcionální_programová­ní
  179. 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/
  180. Pixie: lehký skriptovací jazyk s „kouzelnými“ schopnostmi
    https://www.root.cz/clanky/pixie-lehky-skriptovaci-jazyk-s-kouzelnymi-schopnostmi/
  181. 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/
  182. Stránka projektu Jython
    http://www.jython.org/
  183. Jython (Wikipedia)
    https://en.wikipedia.org/wiki/Jython
  184. Scripting for the Java Platform (Wikipedia)
    https://en.wikipedia.org/wi­ki/Scripting_for_the_Java_Plat­form
  185. JSR 223: Scripting for the JavaTM Platform
    https://jcp.org/en/jsr/detail?id=223
  186. List of JVM languages
    https://en.wikipedia.org/wi­ki/List_of_JVM_languages
  187. Stránka programovacího jazyka Java
    https://www.oracle.com/ja­va/index.html
  188. Stránka programovacího jazyka Clojure
    http://clojure.org
  189. Stránka programovacího jazyka Groovy
    http://groovy-lang.org/
  190. Stránka programovacího jazyka JRuby
    http://jruby.org/
  191. Stránka programovacího jazyka Kotlin
    http://kotlinlang.org/
  192. Stránka programovacího jazyka Scala
    https://www.scala-lang.org/
  193. Projekt Rhino
    https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino
  194. Clojure (Wikipedia)
    https://en.wikipedia.org/wiki/Clojure
  195. Groovy (Wikipedia)
    https://en.wikipedia.org/wi­ki/Groovy_%28programming_lan­guage%29
  196. JRuby (Wikipedia)
    https://en.wikipedia.org/wiki/JRuby
  197. Kotlin (Wikipedia)
    https://en.wikipedia.org/wi­ki/Kotlin_%28programming_lan­guage%29
  198. Scala (Wikipedia)
    https://en.wikipedia.org/wi­ki/Scala_%28programming_lan­guage%29