Obsah
1. Kawa: překvapivě silný a výkonný dialekt Scheme pro JVM
2. LISPovské jazyky pro JVM: Kawa či Clojure?
3. Instalace interpretru a překladače Kawa
4. Nastavení pluginů Slime for Vim a Rainbow parenthesis
5. Základní vlastnosti dialektu Scheme implementovaného v systému Kawa
6. „Numerická věž“ programovacího jazyka Scheme a její rozšíření v Kawě
8. Výpočet konstanty Pi Wallisovým součinem: použití reálných čísel a zlomků
9. Kvaterniony a kvaternionová algebra
10. Kvaterniony v programovacím jazyku Kawa
11. Jednotky u numerických hodnot
12. Použití jednotek v praxi při aritmetických operacích
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
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.
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 |
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á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ázek 2: Po prvním stisku Ctrl+C Ctrl+C se skript zeptá na jméno session (lze pouze potvrdit Enterem).
Obrázek 3: Dále se zeptá na jméno okna (lze taktéž pouze potvrdit Enterem).
Obrázek 4: Vybraná část programu je „magicky“ přenesena do REPL a tam vykonána.
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 |
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
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/wiki/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/5786075364399106425 |
64 | 340282366920938463463374607431768211456/107497803009882761535906756719489104425 |
128 | 115792089237316195423570985008687907853269984665640564039457584007913129639936/36716279764795881321516783116116224837463373080333115741577873817663528415625 |
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ů.
Obrázek 5: Most s pamětní deskou objasňující historii vzniku kvaternionů
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
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
(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/java/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, Clojure i Groovy 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:
19. Literatura
- Peter Seibel
„Practical Common Lisp“
2009 - Paul Graham
„ANSI Common Lisp“
1995 - Gerald Gazdar
„Natural Language Processing in Lisp: An Introduction to Computational Linguistics“
1989 - Peter Norvig
„Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp“
1991 - Alex Mileler et.al.
„Clojure Applied: From Practice to Practitioner“
2015 - „Living Clojure: An Introduction and Training Plan for Developers“
2015 - Dmitri Sotnikov
„Web Development with Clojure: Build Bulletproof Web Apps with Less Code“
2016 - McCarthy
„Recursive functions of symbolic expressions and their computation by machine, part I“
1960 - R. Kent Dybvig
„The Scheme Programming Language“
2009 - Max Hailperin
„Concrete Abstractions“
1998 - Guy L. Steele
„History of Scheme“
2006, Sun Microsystems Laboratories - Kolář J., Muller K.:
„Speciální programovací jazyky“
Praha 1981 - „AutoLISP Release 9, Programmer's reference“
Autodesk Ltd., October 1987 - „AutoLISP Release 10, Programmer's reference“
Autodesk Ltd., September 1988 - 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 - Carl Hewitt; Peter Bishop and Richard Steiger
„A Universal Modular Actor Formalism for Artificial Intelligence“
1973 - Feiman, J.
„The Gartner Programming Language Survey (October 2001)“
Gartner Advisory - 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) - Paul Graham
On Lisp
Prentice Hall, 1993
Dostupné online na stránce http://www.paulgraham.com/onlisptext.html - David S. Touretzky
Common LISP: A Gentle Introduction to Symbolic Computation (Dover Books on Engineering)
- Peter Norvig
Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp - Patrick Winston, Berthold Horn
Lisp (3rd Edition)
ISBN-13: 978–0201083194, ISBN-10: 0201083191 - 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
- Kawa: Compiling Scheme to Java
https://www.mit.edu/afs.new/sipb/project/kawa/doc/kawa-tour.html - Kawa in Languages shootout
http://per.bothner.com/blog/2010/Kawa-in-shootout/ - Kawa 2.0 Supports Scheme R7RS
https://developers.slashdot.org/story/14/12/13/2259225/kawa-20-supports-scheme-r7rs/ - Kawa — fast scripting on the Java platform
https://lwn.net/Articles/623349/ - SLIME (Wikipedia)
http://en.wikipedia.org/wiki/SLIME - slime.vim
http://s3.amazonaws.com/mps/slime.vim - What are the best scheme implementations?
https://www.slant.co/topics/5282/~scheme-implementations - Bigloo homepage
http://www-sop.inria.fr/mimosa/fp/Bigloo/ - FTP s tarbally Bigloo
ftp://ftp-sop.inria.fr/indes/fp/Bigloo - GOTO 2018 • Functional Programming in 40 Minutes • Russ Olsen
https://www.youtube.com/watch?v=0if71HOyVjY - TinyScheme (stránka na Sourceforge)
http://tinyscheme.sourceforge.net/home.html - Embedding Tiny Scheme in a Game
http://www.silicondelight.com/embedding-tiny-scheme-in-a-game/ - Embedding Scheme for a game mission scripting DSL
http://carloscarrasco.com/embedding-scheme-for-a-game-mission-scripting-dsl.html - Všechny verze TinyScheme na SourceForge
https://sourceforge.net/projects/tinyscheme/files/tinyscheme/ - Fork TinyScheme na GitHubu
https://github.com/yawnt/tinyscheme - Ackermannova funkce
https://cs.wikipedia.org/wiki/Ackermannova_funkce - Ackermann function na Rosetta Code
https://rosettacode.org/wiki/Ackermann_function#Scheme - Success Stories (lisp.org)
https://lisp-lang.org/success/ - Allegro Common Lisp Success Stories
https://franz.com/success/ - Clojure Success Stories
https://clojure.org/community/success_stories - Scheme Quick Reference
https://www.st.cs.uni-saarland.de/edu/config-ss04/scheme-quickref.pdf - Slajdy o Scheme (od slajdu číslo 15)
https://docs.google.com/presentation/d/1abmDnKjrq1tcjGvvRNAKhOiSTSE2lyagtcEPal07Gbo/edit - Scheme Cheat Sheet
https://github.com/smythp/scheme-cheat-sheet - Embedding Lua, embedding Guile
http://puntoblogspot.blogspot.com/2013/04/embedding-lua-embedding-guile.html - Lambda Papers
https://en.wikisource.org/wiki/Lambda_Papers - Revised7Report on the Algorithmic Language Scheme
https://small.r7rs.org/attachment/r7rs.pdf - 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/ - Why is Scheme my first language in university?
https://softwareengineering.stackexchange.com/questions/115252/why-is-scheme-my-first-language-in-university - The Perils of JavaSchools
https://www.joelonsoftware.com/2005/12/29/the-perils-of-javaschools-2/ - How to Design Programs, Second Edition
https://htdp.org/2019–02–24/index.html - LilyPond
http://lilypond.org/ - LilyPond — Extending (přes Scheme)
http://lilypond.org/doc/v2.18/Documentation/extending/scheme-tutorial - Scheme in LilyPond
http://lilypond.org/doc/v2.18/Documentation/extending/scheme-in-lilypond - GnuCash
http://www.gnucash.org/ - Custom Reports (in GNU Cash)
https://wiki.gnucash.org/wiki/Custom_Reports - Program by Design
https://programbydesign.org/ - SchemePy
https://pypi.org/project/SchemePy/ - 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 - femtolisp
https://github.com/JeffBezanson/femtolisp - (How to Write a (Lisp) Interpreter (in Python))
http://norvig.com/lispy.html - Repositář s Guile Emacsem
http://git.hcoop.net/?p=bpt/guile.git - Interacting with Guile Compound Data Types in C
http://www.lonelycactus.com/guilebook/x1555.html - Calling Guile functions from C
http://www.lonelycactus.com/guilebook/c1204.html#SECCALLGUILEFUNC - Arrays, and other compound data types
http://www.lonelycactus.com/guilebook/charrays.html - Interacting with Guile Compound Data Types in C
http://www.lonelycactus.com/guilebook/x1555.html - Guile Reference Manual
https://www.gnu.org/software/guile/manual/html_node/index.html - Scheme: Summary of Common Syntax
https://www.gnu.org/software/guile/manual/html_node/Syntax-Summary.html#Syntax-Summary - Scripting with Guile: Extension language enhances C and Scheme
https://www.ibm.com/developerworks/library/l-guile/index.html - Having fun with Guile: a tutorial
http://dustycloud.org/misc/guile-tutorial.html - Guile: Loading Readline Support
https://www.gnu.org/software/guile/manual/html_node/Loading-Readline-Support.html#Loading-Readline-Support - lispy
https://pypi.org/project/lispy/ - Lython
https://pypi.org/project/Lython/ - Lizpop
https://pypi.org/project/lizpop/ - Budoucnost programovacích jazyků
http://www.knesl.com/budoucnost-programovacich-jazyku - LISP Prolog and Evolution
http://blog.samibadawi.com/2013/05/lisp-prolog-and-evolution.html - List of Lisp-family programming languages
https://en.wikipedia.org/wiki/List_of_Lisp-family_programming_languages - clojure_py na indexu PyPi
https://pypi.python.org/pypi/clojure_py - PyClojure
https://github.com/eigenhombre/PyClojure - Hy na GitHubu
https://github.com/hylang/hy - Hy: The survival guide
https://notes.pault.ag/hy-survival-guide/ - Hy běžící na monitoru terminálu společnosti Symbolics
http://try-hy.appspot.com/ - Welcome to Hy’s documentation!
http://docs.hylang.org/en/stable/ - Hy na PyPi
https://pypi.org/project/hy/#description - Getting Hy on Python
https://lwn.net/Articles/596626/ - Programming Can Be Fun with Hy
https://opensourceforu.com/2014/02/programming-can-fun-hy/ - Přednáška o projektu Hy (pětiminutový lighttalk)
http://blog.pault.ag/day/2013/04/02 - Hy (Wikipedia)
https://en.wikipedia.org/wiki/Hy - GNU Emacs Lisp Reference Manual: Point
https://www.gnu.org/software/emacs/manual/html_node/elisp/Point.html - GNU Emacs Lisp Reference Manual: Narrowing
https://www.gnu.org/software/emacs/manual/html_node/elisp/Narrowing.html - GNU Emacs Lisp Reference Manual: Functions that Create Markers
https://www.gnu.org/software/emacs/manual/html_node/elisp/Creating-Markers.html - GNU Emacs Lisp Reference Manual: Motion
https://www.gnu.org/software/emacs/manual/html_node/elisp/Motion.html#Motion - GNU Emacs Lisp Reference Manual: Basic Char Syntax
https://www.gnu.org/software/emacs/manual/html_node/elisp/Basic-Char-Syntax.html - Elisp: Sequence: List, Array
http://ergoemacs.org/emacs/elisp_list_vs_vector.html - Elisp: Property List
http://ergoemacs.org/emacs/elisp_property_list.html - Elisp: Hash Table
http://ergoemacs.org/emacs/elisp_hash_table.html - Elisp: Association List
http://ergoemacs.org/emacs/elisp_association_list.html - The mapcar Function (An Introduction to Programming in Emacs Lisp)
https://www.gnu.org/software/emacs/manual/html_node/eintr/mapcar.html - Anaphoric macro
https://en.wikipedia.org/wiki/Anaphoric_macro - Some Common Lisp Loop Macro Examples
https://www.youtube.com/watch?v=3yl8o6r_omw - A Guided Tour of Emacs
https://www.gnu.org/software/emacs/tour/ - The Roots of Lisp
http://www.paulgraham.com/rootsoflisp.html - Evil (Emacs Wiki)
https://www.emacswiki.org/emacs/Evil - Evil (na GitHubu)
https://github.com/emacs-evil/evil - Evil (na stránkách repositáře MELPA)
https://melpa.org/#/evil - Evil Mode: How I Switched From VIM to Emacs
https://blog.jakuba.net/2014/06/23/evil-mode-how-to-switch-from-vim-to-emacs.html - GNU Emacs (home page)
https://www.gnu.org/software/emacs/ - GNU Emacs (texteditors.org)
http://texteditors.org/cgi-bin/wiki.pl?GnuEmacs - An Introduction To Using GDB Under Emacs
http://tedlab.mit.edu/~dr/gdbintro.html - An Introduction to Programming in Emacs Lisp
https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html - 27.6 Running Debuggers Under Emacs
https://www.gnu.org/software/emacs/manual/html_node/emacs/Debuggers.html - GdbMode
http://www.emacswiki.org/emacs/GdbMode - Emacs (Wikipedia)
https://en.wikipedia.org/wiki/Emacs - Emacs timeline
http://www.jwz.org/doc/emacs-timeline.html - Emacs Text Editors Family
http://texteditors.org/cgi-bin/wiki.pl?EmacsFamily - Vrapper aneb spojení možností Vimu a Eclipse
https://mojefedora.cz/vrapper-aneb-spojeni-moznosti-vimu-a-eclipse/ - 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/ - Emacs/Evil-mode – A basic reference to using evil mode in Emacs
http://www.aakarshnair.com/posts/emacs-evil-mode-cheatsheet - From Vim to Emacs+Evil chaotic migration guide
https://juanjoalvarez.net/es/detail/2014/sep/19/vim-emacsevil-chaotic-migration-guide/ - Introduction to evil-mode {video)
https://www.youtube.com/watch?v=PeVQwYUxYEg - EINE (Emacs Wiki)
http://www.emacswiki.org/emacs/EINE - EINE (Texteditors.org)
http://texteditors.org/cgi-bin/wiki.pl?EINE - ZWEI (Emacs Wiki)
http://www.emacswiki.org/emacs/ZWEI - ZWEI (Texteditors.org)
http://texteditors.org/cgi-bin/wiki.pl?ZWEI - Zmacs (Wikipedia)
https://en.wikipedia.org/wiki/Zmacs - Zmacs (Texteditors.org)
http://texteditors.org/cgi-bin/wiki.pl?Zmacs - TecoEmacs (Emacs Wiki)
http://www.emacswiki.org/emacs/TecoEmacs - Micro Emacs
http://www.emacswiki.org/emacs/MicroEmacs - Micro Emacs (Wikipedia)
https://en.wikipedia.org/wiki/MicroEMACS - EmacsHistory
http://www.emacswiki.org/emacs/EmacsHistory - Seznam editorů s ovládáním podobným Emacsu či kompatibilních s příkazy Emacsu
http://www.finseth.com/emacs.html - evil-numbers
https://github.com/cofi/evil-numbers - Debuggery a jejich nadstavby v Linuxu (1.část)
http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu/ - Debuggery a jejich nadstavby v Linuxu (2.část)
http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-2-cast/ - Debuggery a jejich nadstavby v Linuxu (3): Nemiver
http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-3-nemiver/ - Debuggery a jejich nadstavby v Linuxu (4): KDbg
http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-4-kdbg/ - 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/ - Org mode
https://orgmode.org/ - The Org Manual
https://orgmode.org/manual/index.html - Kakoune (modální textový editor)
http://kakoune.org/ - Vim-style keybinding in Emacs/Evil-mode
https://gist.github.com/troyp/6b4c9e1c8670200c04c16036805773d8 - Emacs – jak začít
http://www.abclinuxu.cz/clanky/navody/emacs-jak-zacit - Programovací jazyk LISP a LISP machines
https://www.root.cz/clanky/programovaci-jazyk-lisp-a-lisp-machines/ - Evil-surround
https://github.com/emacs-evil/evil-surround - Spacemacs
http://spacemacs.org/ - Lisp: Common Lisp, Racket, Clojure, Emacs Lisp
http://hyperpolyglot.org/lisp - Common Lisp, Scheme, Clojure, And Elisp Compared
http://irreal.org/blog/?p=725 - Does Elisp Suck?
http://irreal.org/blog/?p=675 - Emacs pro mírně pokročilé (9): Elisp
https://www.root.cz/clanky/emacs-elisp/ - If I want to learn lisp, are emacs and elisp a good choice?
https://www.reddit.com/r/emacs/comments/2m141y/if_i_want_to_learn_lisp_are_emacs_and_elisp_a/ - Clojure(Script) Interactive Development Environment that Rocks!
https://github.com/clojure-emacs/cider - An Introduction to Emacs Lisp
https://harryrschwartz.com/2014/04/08/an-introduction-to-emacs-lisp.html - Emergency Elisp
http://steve-yegge.blogspot.com/2008/01/emergency-elisp.html - Lambda calculus
https://en.wikipedia.org/wiki/Lambda_calculus - John McCarthy's original LISP paper from 1959
https://www.reddit.com/r/programming/comments/17lpz4/john_mccarthys_original_lisp_paper_from_1959/ - Micro Manual LISP
https://www.scribd.com/document/54050141/Micro-Manual-LISP - How Lisp Became God's Own Programming Language
https://twobithistory.org/2018/10/14/lisp.html - History of Lisp
http://jmc.stanford.edu/articles/lisp/lisp.pdf - The Roots of Lisp
http://languagelog.ldc.upenn.edu/myl/llog/jmc.pdf - Racket
https://racket-lang.org/ - The Racket Manifesto
http://felleisen.org/matthias/manifesto/ - MIT replaces Scheme with Python
https://www.johndcook.com/blog/2009/03/26/mit-replaces-scheme-with-python/ - Adventures in Advanced Symbolic Programming
http://groups.csail.mit.edu/mac/users/gjs/6.945/ - Why MIT Switched from Scheme to Python (2009)
https://news.ycombinator.com/item?id=14167453 - Starodávná stránka XLispu
http://www.xlisp.org/ - AutoLISP
https://en.wikipedia.org/wiki/AutoLISP - Seriál PicoLisp: minimalistický a výkonný interpret Lispu
https://www.root.cz/serialy/picolisp-minimalisticky-a-vykonny-interpret-lispu/ - Common Lisp
https://common-lisp.net/ - Getting Going with Common Lisp
https://cliki.net/Getting%20Started - Online Tutorial (Common Lisp)
https://cliki.net/online%20tutorial - Guile Emacs
https://www.emacswiki.org/emacs/GuileEmacs - Guile Emacs History
https://www.emacswiki.org/emacs/GuileEmacsHistory - Guile is a programming language
https://www.gnu.org/software/guile/ - MIT Scheme
http://groups.csail.mit.edu/mac/projects/scheme/ - SIOD: Scheme in One Defun
http://people.delphiforums.com/gjc//siod.html - CommonLispForEmacs
https://www.emacswiki.org/emacs/CommonLispForEmacs - Elisp: print, princ, prin1, format, message
http://ergoemacs.org/emacs/elisp_printing.html - Special Forms in Lisp
http://www.nhplace.com/kent/Papers/Special-Forms.html - Basic Building Blocks in LISP
https://www.tutorialspoint.com/lisp/lisp_basic_syntax.htm - Introduction to LISP – University of Pittsburgh
https://people.cs.pitt.edu/~milos/courses/cs2740/Lectures/LispTutorial.pdf - Why don't people use LISP
https://forums.freebsd.org/threads/why-dont-people-use-lisp.24572/ - Structured program theorem
https://en.wikipedia.org/wiki/Structured_program_theorem - Clojure: API Documentation
https://clojure.org/api/api - Tutorial for the Common Lisp Loop Macro
http://www.ai.sri.com/pkarp/loop.html - Common Lisp's Loop Macro Examples for Beginners
http://www.unixuser.org/~euske/doc/cl/loop.html - A modern list api for Emacs. No 'cl required.
https://github.com/magnars/dash.el - The LOOP Facility
http://www.lispworks.com/documentation/HyperSpec/Body/06_a.htm - Clojure.org: Vars and the Global Environment
http://clojure.org/Vars - Clojure.org: Refs and Transactions
http://clojure.org/Refs - Clojure.org: Atoms
http://clojure.org/Atoms - Clojure.org: Agents as Asynchronous Actions
http://clojure.org/agents - Transient Data Structureshttp://clojure.org/transients
- Dynamic Languages Strike Back
http://steve-yegge.blogspot.cz/2008/05/dynamic-languages-strike-back.html - Scripting: Higher Level Programming for the 21st Century
http://www.tcl.tk/doc/scripting.html - Clojure (na Wikipedia EN)
http://en.wikipedia.org/wiki/Clojure - Clojure (na Wikipedia CS)
http://cs.wikipedia.org/wiki/Clojure - SICP (The Structure and Interpretation of Computer Programs)
http://mitpress.mit.edu/sicp/ - Pure function
http://en.wikipedia.org/wiki/Pure_function - Funkcionální programování
http://cs.wikipedia.org/wiki/Funkcionální_programování - 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/ - Pixie: lehký skriptovací jazyk s „kouzelnými“ schopnostmi
https://www.root.cz/clanky/pixie-lehky-skriptovaci-jazyk-s-kouzelnymi-schopnostmi/ - Programovací jazyk Pixie: funkce ze základní knihovny a použití FFI
https://www.root.cz/clanky/programovaci-jazyk-pixie-funkce-ze-zakladni-knihovny-a-pouziti-ffi/ - Stránka projektu Jython
http://www.jython.org/ - Jython (Wikipedia)
https://en.wikipedia.org/wiki/Jython - Scripting for the Java Platform (Wikipedia)
https://en.wikipedia.org/wiki/Scripting_for_the_Java_Platform - JSR 223: Scripting for the JavaTM Platform
https://jcp.org/en/jsr/detail?id=223 - List of JVM languages
https://en.wikipedia.org/wiki/List_of_JVM_languages - Stránka programovacího jazyka Java
https://www.oracle.com/java/index.html - Stránka programovacího jazyka Clojure
http://clojure.org - Stránka programovacího jazyka Groovy
http://groovy-lang.org/ - Stránka programovacího jazyka JRuby
http://jruby.org/ - Stránka programovacího jazyka Kotlin
http://kotlinlang.org/ - Stránka programovacího jazyka Scala
https://www.scala-lang.org/ - Projekt Rhino
https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino - Clojure (Wikipedia)
https://en.wikipedia.org/wiki/Clojure - Groovy (Wikipedia)
https://en.wikipedia.org/wiki/Groovy_%28programming_language%29 - JRuby (Wikipedia)
https://en.wikipedia.org/wiki/JRuby - Kotlin (Wikipedia)
https://en.wikipedia.org/wiki/Kotlin_%28programming_language%29 - Scala (Wikipedia)
https://en.wikipedia.org/wiki/Scala_%28programming_language%29