Obsah
1. Racket – programovací jazyk a současně i platforma pro vývoj nových jazyků
3. Integrované vývojové prostředí a interaktivní smyčka REPL
4. Základy programovacího jazyka Racket
5. Numerická věž a příslušné základní predikáty
6. Funkce jako základní stavební bloky programů
7. Pojmenování uživatelských funkcí
9. Anonymní funkce s proměnným počtem parametrů
10. Pojmenované funkce s proměnným počtem parametrů
11. Povinné a nepovinné parametry anonymních funkcí
12. Povinné a nepovinné parametry pojmenovaných funkcí
13. Parametry anonymních funkcí explicitně specifikované svým jménem
14. Parametry pojmenovaných funkcí specifikované jménem
15. Pojmenované a nepojmenované funkce s různou aritou
17. Obsah následující části seriálu
18. Repositář s demonstračními příklady
1. Racket – programovací jazyk a současně i platforma pro vývoj nových jazyků
V dnešní části seriálu o rozsáhlém a možná i poněkud chaotickém světě lispovských programovacích jazyků se seznámíme se základními vlastnostmi systému nazvaného Racket. Naprostá většina programovacích jazyků (což většinou byly různé varianty Scheme či LISPu), s nimiž jsme se až doposud seznámili, sestávala z interpretru a/nebo překladače, který byl doplněn o interaktivní smyčku REPL a taktéž o základní podpůrné knihovny. Systém Racket se ovšem z tohoto ustáleného schématu poněkud vymyká, protože kromě již zmíněných modulů – interpretru, překladače, REPL, základních knihoven – obsahuje i integrované vývojové prostředí, opravdu rozsáhlé množství knihoven a navíc systém pro snadnou instalaci dalších knihoven (či možná lépe řečeno celých balíčků).
Ale to není zdaleka vše, protože samotný programovací jazyk Racketu je poměrně snadno rozšiřitelný a modifikovatelný, takže vzniklo hned několik jeho variant. Kromě klasického dynamicky typovaného jazyka Scheme je tak možné použít jazyk s možností přesné deklarace datových typů, jazyk s infixovu notací zápisu aritmetických výrazů, dokonce i implementaci Algolu 60 atd. (samotný dialekt se vybírá pomocí řádku začínajícího na #lang, což uvidíme v demonstračních příkladech).
Dnes se však seznámíme především s první zmíněnou variantou programovacího jazyka Racket, přesněji řečeno s jedním dialektem programovacího jazyka Scheme s dynamickým typovým systémem (typ je odvozen od hodnoty, nemusí být specifikován u proměnné ani u parametru funkce). Uvidíme, že i „základní dialekt Scheme“ doznal několika užitečných rozšíření. Teprve v navazujících článcích si ukážeme i další rozšíření tohoto jazyka o další syntaxi a taktéž o novou sémantiku (což je důležitější, než samotný způsob zápisu).

Obrázek 1: Logo systému Racket.
2. Instalace systému Racket
Instalace celého systému Racket, včetně již výše zmíněného vývojového prostředí, je poměrně jednoduchá, protože postačuje ze stránky https://download.racket-lang.org/ stáhnout instalační soubor připravený pro vámi používaný operační systém, což je v případě Linuxu BASH script, na jehož konci je celý systém Racket zabalený. Tento soubor získáme například s využitím nástroje wget (nebo libovolným webovým prohlížečem):
$ wget https://mirror.racket-lang.org/installers/7.4/racket-7.4-x86_64-linux.sh
Po stažení tohoto souboru je možné ho spustit, a to dokonce i bez práv roota, ideálně pod novým uživatelem, který bude mít přístup jen k Racketu:
$ bash racket-7.4-x86_64-linux.sh
Na začátku nám instalační skript položí několik otázek:
This program will extract and install Racket v7.4. Note: the required diskspace for this installation is 523M. Do you want a Unix-style distribution? In this distribution mode files go into different directories according to Unix conventions. A "racket-uninstall" script will be generated to be used when you want to remove the installation. If you say 'no', the whole Racket directory is kept in a single installation directory (movable and erasable), possibly with external links into it -- this is often more convenient, especially if you want to install multiple versions or keep it in your home directory. Enter yes/no (default: no) >
Povšimněte si, že instalační skript nám nabízí dvě možnosti instalace. První takzvaná „unixová“ varianta spočívá v tom, že se Racket nainstaluje do běžné adresářové struktury, na kterou jsme zvyklí z Unixových systémů: spustitelné soubory budou uloženy v adresáři /usr/bin, manuálové stránky v adresáři /usr/share/man atd. atd. Pro tento typ instalace pochopitelně budete potřebovat práva roota a navíc koliduje se správcem balíčků dané distribuce. Předností je, že lze snadno vytvářet spustitelné skripty programované v Racketu. Tyto skripty musí mít nastaven příznak +x a musí začínat řádkem s klasickým „she-bangem“:
#!/usr/bin/env racket
Výhodnější ovšem může být, zejména ve chvíli, kdy Racket má používat jen jediný uživatel, alternativní způsob instalace, který spočívá v tom, že se Racket rozbalí do zvoleného adresáře. Tím může být například adresář /opt nebo je pochopitelně možné instalaci provést přímo do domovského adresáře toho uživatele, který instalaci provádí:
Enter yes/no (default: no) > no
Po odpovědi „no“ se instalační skript zeptá, do jakého adresáře se má tedy instalace provést:
Where do you want to install the "racket" directory tree? 1 - /usr/racket [default] 2 - /usr/local/racket 3 - ~/racket (/home/tester/racket) 4 - ./racket (here) Or enter a different "racket" directory to install in. > 4
Samotná instalace proběhne poměrně rychle, a to i přesto, že se na disku obsadí relativně velké množství prostoru: více než 460 MB (což je skutečně hodně, i když samotný instalační skript hlásí dokonce ještě větší číslo):
Checking the integrity of the binary archive... ok. Unpacking into "/opt/racket" (Ctrl+C to abort)... Done. If you want to install new system links within the "bin", "man" and "share/applications" subdirectories of a common directory prefix (for example, "/usr/local") then enter the prefix of an existing directory that you want to use. This might overwrite existing symlinks, but not files.
Adresářová struktura nainstalovaného systému Racket vypadá následovně:
. ├── bin ├── collects │ ├── acks │ ├── compiler │ ├── data │ ├── db │ ├── dynext │ ├── ffi │ ├── file │ ├── info │ ├── info-domain │ ├── json │ ├── launcher │ ├── net │ ├── openssl │ ├── pkg │ ├── planet │ ├── racket │ ├── raco │ ├── reader │ ├── realm │ ├── setup │ ├── s-exp │ ├── syntax │ ├── version │ └── xml ├── doc │ ├── 2d │ ├── acks │ ├── algol60 │ ├── browser │ ├── bug-report │ ├── cards │ ├── compatibility │ ├── continue │ ├── contract-profile │ ├── cookies │ ├── data │ ├── datalog │ ├── db │ ├── deinprogramm │ ├── demo-m1 │ ├── demo-m2 │ ├── demo-manual-m1 │ ├── demo-manual-m2 │ ├── demo-manual-s1 │ ├── demo-manual-s2 │ ├── demo-s1 │ ├── demo-s2 │ ├── distributed-places │ ├── draw │ ├── drracket │ ├── drracket-tools │ ├── ds-store │ ├── dynext │ ├── embedded-gui │ ├── eopl │ ├── errortrace │ ├── file │ ├── foreign │ ├── framework │ ├── frtime │ ├── future-visualizer │ ├── games │ ├── getting-started │ ├── gl-board-game │ ├── graphics │ ├── gui │ ├── guide │ ├── help │ ├── htdp │ ├── htdp-langs │ ├── htdp-ptr │ ├── html │ ├── images │ ├── inside │ ├── json │ ├── lazy │ ├── license │ ├── local-redirect │ ├── macro-debugger │ ├── make │ ├── math │ ├── more │ ├── mrlib │ ├── mysterx │ ├── mzcom │ ├── mzlib │ ├── mzscheme │ ├── net │ ├── openssl │ ├── optimization-coach │ ├── option-contract │ ├── osx-ssl │ ├── parser-tools │ ├── pict │ ├── pict-snip │ ├── picturing-programs │ ├── pkg │ ├── plai │ ├── planet │ ├── plot │ ├── plt-installer │ ├── preprocessor │ ├── profile │ ├── quick │ ├── quickscript │ ├── r5rs │ ├── r6rs │ ├── racket-cheat │ ├── racklog │ ├── rackunit │ ├── raco │ ├── readline │ ├── redex │ ├── reference │ ├── release │ ├── sasl │ ├── scheme │ ├── scribble │ ├── scribble-pp │ ├── scriblib │ ├── search │ ├── sgl │ ├── slatex-wrap │ ├── slideshow │ ├── source-syntax │ ├── srfi │ ├── srfi-nf │ ├── stepper │ ├── string-constants │ ├── style │ ├── swindle │ ├── syntax │ ├── syntax-color │ ├── teachpack │ ├── test-engine │ ├── tool │ ├── tools │ ├── trace │ ├── ts-guide │ ├── ts-reference │ ├── turtles │ ├── unix-socket │ ├── version │ ├── web-server │ ├── web-server-internal │ ├── win32-ssl │ ├── xml │ └── xrepl ├── etc ├── include ├── lib ├── man │ └── man1 └── share ├── applications └── pkgs
Nastavení proměnné prostředí PATH takovým způsobem, aby bylo možné jednoduše spustit interpret i REPL:
$ whereis racket racket: /opt/racket/bin/racket $ export PATH=$PATH:/opt/racket/bin $ whereis racket racket: /opt/racket/bin/racket $ racket --version Welcome to Racket v7.4.
export PATH=$PATH:~/bin:~/.local/bin/:/opt/go/bin:~/go/bin:/opt/racket/bin
3. Integrované vývojové prostředí a interaktivní smyčka REPL
Po doufejme že úspěšné instalaci Racketu máme hned několik možností, jak celý systém začít používat. Můžeme například spustit jeho integrované vývojové prostředí:
/opt/racket/bin $ ./drracket

Obrázek 2: Spuštění IDE systému Racket.
Prozatím si však vystačíme s interaktivní smyčkou REPL, kterou spustíme příkazem racket:
/opt/racket/bin $ ./racket Welcome to Racket v7.4.

Obrázek 3: Výběr jazyka a dialektu.
Interaktivní smyčka je použitelná prakticky stejným způsobem, jako ostatní REPL, s nimiž jsme se až doposud seznámili ve článcích o jazycích Guile, TinyScheme, PicoLispu, systému Kawa atd. Jednotlivé formy jsou ihned po svém zápisu vyhodnocovány. Nejjednodušší je pochopitelně situace ve chvíli, kdy je celá forma zapsána na jediném řádku:
> (+ 1 1) 2 > (* 6 7) 42
Formy zapisované na více řádcích jsou vyhodnoceny až se zápisem poslední pravé kulaté závorky:
> (+ 1 2 ) 3
K dispozici je i nápověda, která se ovšem neotevře přímo v terminálu, ale ve webovém prohlížeči:
> (help random) Loading help index... Sending to web browser... file: /opt/racket/doc/reference/generic-numbers.html anchor: (def._((lib._racket/private/base..rkt)._random))

Obrázek 4: Nápověda zobrazená ve webovém prohlížeči.
4. Základy programovacího jazyka Racket
Ve druhé části článku se seznámíme se základními vlastnostmi programovacího jazyka Racket. Ten vychází z jazyka Scheme, takže většina dále popsaných příkladů již může být čtenářům tohoto seriálu již dobře známa. Zaměříme se především na tři sice základní, ale o to důležitější součásti programovacího jazyka Racket:
- Práci s numerickými hodnotami a využitím celé takzvané „numerické věže“
- Definicí pojmenovaných i anonymních funkcí, včetně funkcí s proměnným počtem parametrů, nepovinnými parametry, tzv. keywords parametry atd. Funkce jsou základním stavebním prvkem funkcionálních jazyků, takže je dobré znát všechny jejich možnosti (některé vlastnosti lze plně využít pouze při přímém použití anonymních funkcí).
- Některými základními speciálními formami určenými pro ovlivnění běhu programu. Jedná se pochopitelně o podmínky a taktéž o programové smyčky.
5. Numerická věž a příslušné základní predikáty
S takzvanou „numerickou věží“ jsme se již v tomto seriálu setkali při popisu možností dalších dialektů programovacího jazyka Scheme. Připomeňme si ve stručnosti, že se jedná o hierarchii datových typů reprezentujících různé typy čísel. Na vrcholu této hierarchie stojí obecný typ number, pod ním leží komplexní čísla, dále čísla reálná, čísla racionální (zlomky) a nakonec čísla celá:
# | Typ | Význam |
---|---|---|
1 | number | libovolná obecná čísla |
2 | complex | komplexní čísla |
3 | real | reálná čísla |
4 | rational | zlomky (racionální čísla) |
5 | integer | celá čísla |
Převody mezi numerickými typy jsou prováděny automaticky na základě vyhodnocovaného výrazu. Například v následujícím výrazu bylo nutné vyhodnotit výsledek jako komplexní číslo, protože jsme se snažili vypočítat druhou odmocninu ze záporného čísla:
(sqrt (/ 3.14159 (- (expt 2 32)))) 0+2.704548801180264e-05i
V jazyce Racket dále existuje velké množství predikátů určených pro zjištění, jakého typu je daná hodnota (a zda se vůbec jedná o číslo). Povšimněte si, že některé predikáty slouží pro zjištění, zda se jedná o „přesná“ či naopak „nepřesná“ čísla. Mezi „přesná čísla“ patří ty hodnoty, jejichž reálná i imaginární část je buď celé číslo nebo zlomek (pozor na rozdíl mezi reálnou části komplexního čísla a reálným číslem):
# | Predikát | Stručný popis | |
---|---|---|---|
1 | number? | test, zda se jedná o jakoukoli numerickou hodnotu | |
2 | complex? | test, zda se jedná o komplexní číslo | |
3 | real? | test, zda se jedná o reálné číslo | |
4 | rational? | test, zda se jedná o racionální číslo (zlomek) | |
5 | integer? | test, zda se jedná o celé číslo | |
6 | exact-integer? | test, zda se jedná o „přesné“ celé číslo | |
7 | exact-nonnegative-integer? | test, zda se jedná o „přesné“ celé nezáporné číslo | |
8 | exact-positive-integer? | test, zda se jedná o „přesné“ celé kladné číslo | |
9 | inexact-real? | test, zda se jedná o „nepřesné“ reálné číslo | |
10 | zero? | test na nulu | |
11 | positive? | test na kladné číslo | |
12 | negative? | test na záporné číslo | |
13 | even? | test na sudé číslo | |
14 | odd? | test na liché číslo | |
15 | exact? | test na libovolné „přesné“ číslo | |
16 | inexact? | test na libovolné „nepřesné“ číslo |
6. Funkce jako základní stavební bloky programů
Naprostým základem při tvorbě každé jen trošku rozsáhlejší aplikace je dekompozice problému na menší části, které je možné realizovat snadněji, protože se výchozí problém více konkretizuje (a přibližuje se tak jak možnostem použitého programovacího jazyka, tak i schopnosti vývojáře problém naprogramovat :-). V programovacím jazyku Racket se, podobně jako v mnoha dalších imperativních a především funkcionálních programovacích jazycích, pro rozklad problému na menší části používají uživatelsky definované funkce, a to jak funkce pojmenované (navázané na nějaký symbol – jméno), tak i funkce anonymní (tento typ funkcí je představován lambda výrazy).
V této kapitole si popíšeme způsob tvorby pojmenovaných funkcí a v kapitole osmé se budeme zabývat problémem tvorby funkcí anonymních, s čímž souvisí i problematika vytvoření a následného použití lokálních proměnných. Možná by na tomto místě bylo vhodné připomenout, že z čistě teoretického hlediska by se měly anonymní funkce popsat dříve než funkce pojmenované, protože právě anonymní funkce tvoří základ pro vytváření jak funkcí pojmenovaných, tak i lokálních proměnných (a mnoha dalších užitečných jazykových konstrukcí). Vytvoření uživatelské pojmenované funkce je v programovacím jazyku Racket velmi jednoduché – použije se speciální forma define, za níž se do seznamu zapíše jméno nově vytvářené funkce i jména jejích formálních parametrů. Za tímto seznamem následuje tělo funkce, tj. výraz či sekvence výrazů, které se mají vyhodnotit (v těchto výrazech je samozřejmě možné používat formální parametry funkce).
Hodnota posledního vyhodnoceného výrazu se stává i návratovou hodnotou celé funkce, což mj. znamená, že všechny předchozí výrazy musí mít vedlejší efekt, jinak je jejich volání (použití v těle funkce) vlastně zbytečné.
Formálně vypadá vytvoření nové funkce následovně:
(define ([jméno funkce] [formální parametry]) [tělo funkce])
Definice konkrétní pojmenované funkce bez parametrů (vrací konstantu 0) a její následné zavolání:
(define (nothing) 0) (nothing) 0
Postup vytvoření uživatelské funkce s jedním parametrem a jejího následného použití:
(define (square x) (* x x)) (square 42) 1764 (square (+ 1 2)) 9 (+ (square 3) (square 4)) 25
Samozřejmě je možné vytvořit i funkci víceparametrickou, zde konkrétně funkci pro výpočet hodnoty kvadratické funkce ve tvaru y=ax2+bx+c pro zadanou hodnotu x:
(define (quadratic a b c x) (+ (* a x x) (* b x) c)) (quadratic 1 0 0 1) 1 (quadratic 2 2 2 4) 42
Ve funkci je možné vytvořit blok s lokálními proměnnými formou let:
(define (square x) (let ((result (* x x))) result))
Ovšem let lze použít i mimo definici funkce pro vytvoření lokálních proměnných (přesněji řečeno lokálního navázání symbolu/symbolů na určité hodnoty):
(define (add x y) (+ x y)) (print (let ((x 10) (y 20)) (add x y)))
7. Pojmenování uživatelských funkcí
V programovacím jazyku Racket lze vytvářet i funkce, v jejichž názvu se nachází různé nealfanumerické znaky. Je to ostatně logické, protože se jedná o jeden z těch jazyků (a je jich překvapivě velké množství), v nichž neexistují ani operátory (zapisované většinou právě pomocí nealfanumerických znaků) ani většina dalších speciálních syntaktických konstrukcí. V předchozích částech tohoto seriálu jsme si již ukázali některé predikáty, u nichž je obvyklé, že jsou jejich jména ukončena znakem otazník (?):
# | Funkce (predikát) |
---|---|
1 | exact? |
2 | inexact? |
3 | odd? |
4 | even? |
5 | zero? |
6 | positive? |
7 | negative? |
8 | eq? |
9 | eqv? |
10 | equal? |
11 | null? |
12 | number? |
Také jsme se seznámili s konverzními funkcemi používajícími ve svém názvu dvojici znaků ->. Mnohdy se také můžeme setkat s tím, že se jméno uživatelské funkce skládá z více slov oddělených pomlčkou (-), která je v jiných programovacích jazycích většinou rezervována pro zápis operátoru rozdílu, popř. změny znaménka. V následujících příkladech je ukázáno, že jména uživatelských funkcí mohou opravdu obsahovat téměř jakýkoli nealfanumerický znak (výjimek je pouze několik, vypsány jsou pochopitelně v manuálu jazyka Racket a většinou se jedná o různé formy závorek a taktéž o znak #):
(define (>= x y) (or (> x y) (= x y)) ) ; druhá možná definice (define (>= x y) (not (< x y)) )
První přiblížení k tomu, jak by se mohl zapsat ternární výraz. Tento příklad však má jeden poměrně závažný nedostatek vyplývající z vlastnosti jazyka Racket (a obecně jakéhokoli lispovského jazyka). Dokážete přijít na to, o jaký nedostatek se jedná?
(define (?: podminka prvni-vyraz druhy-vyraz) (if podminka prvni-vyraz druhy-vyraz) ) ; test (?: #t 1 2) 1 ; další test (?: #f 1 2) 2 ; Při tisku jednotlivých slov lze namísto ; řetězců použít i takzvané symboly uvozené apostrofem (?: (< 1 2) 'mensi 'vetsi) mensi (?: (< 2 1) 'mensi 'vetsi) vetsi
Programátoři znalí Basicu :-) pravděpodobně znají operátor <> (nerovnost), který lze v jazyku Racket velmi jednoduše vytvořit jako uživatelskou funkci:
(define (<> x y) (not (= x y))) (<> 1 2) #t (<> 1 1) #f
Ovšem výše uvedenou funkci můžeme též zobecnit na libovolný typ parametrů:
(define (<> a b) (not (equal? a b))) (<> 'a 'b) #t (<> "hello" "world") #t (<> "hello" "hello") #f
8. Anonymní funkce
Kromě pojmenovaných funkcí popsaných v předchozích dvou kapitolách je možné v programovacím jazyce Racket, podobně jako v LISPu a pochopitelně i v klasickém Scheme, ale i mnoha dalších jazycích umožňujících funkcionální programování, vytvářet a používat takzvané funkce anonymní. Tyto funkce, které je možné s výhodou využít například při zápisu iterací nad prvky seznamů či při omezování oblasti platnosti proměnných, se vytváří s využitím speciální formy lambda, jejíž název je odvozen ze slavné Churchovy teorie Lambda kalkulu, která má poměrně velký význam jak v teoretické informatice, tak i v dalších odvětvích informatiky (viz též odkazy uvedené v poslední kapitole). Samotný zápis anonymní funkce se příliš neliší od zápisu funkce pojmenované – jediný syntaktický rozdíl spočívá v tom, že se při zápisu speciální formy lambda nikde neuvádí jméno funkce, pouze seznam (jména) formálních parametrů, za nimiž následuje tělo funkce:
(lambda ([formální parametry]) [tělo anonymní funkce])
; pouze vytvoření anonymní funkce bez ; jejího dalšího použití (umělý příklad, který ; nemá větší význam, protože se anonymní funkce ; nikde nevolá) > (lambda (x) (* x x)) #
Ihned po vytvoření anonymní funkce je ji možné zavolat:
; vytvoření anonymní funkce s jejím následným ; zavoláním s parametrem 42 ((lambda (x) (* x x)) 42) 1764
Příklad použití anonymní funkce s více parametry:
; anonymní funkce s více parametry (lambda (a b c) (+ a b c)) #<procedure #f (a b c)> ((lambda (a b c) (+ a b c)) 1 2 3) 6
Mezi funkcemi pojmenovanými a anonymními existuje velmi úzká vazba, kterou si můžeme vysvětlit na jednoduchém příkladu. Mějme uživatelskou funkci nazvanou plus, která sečte své dva parametry (pro jednoduchost považujme tyto parametry vždy za čísla) a vrátí součet hodnot obou parametrů. Definice takové funkce je velmi jednoduchá:
(define (plus x y) (+ x y)) ; test (plus 1 2) 3
Výše uvedený zápis je ekvivalentní s následujícím zápisem, ve kterém se vytváří proměnná nazvaná plus, která jako svoji hodnotu obsahuje (anonymní) funkci. Již v úvodním článku o programovacím jazyku Scheme jsme si řekli, že funkce lze používat na stejných místech jako hodnoty jiných typů, takže je tento zápis korektní (a to i v Racketu, který je, jak již víme, ze Scheme odvozen):
(define plus (lambda (x y) (+ x y))) ; zjistíme, jaká hodnota je na symbol plus navázána plus #<procedure:plus> ; test (plus 1 2) 3
9. Anonymní funkce s proměnným počtem parametrů
Kromě anonymních funkcí, v nichž jsou explicitně vyjmenovány všechny jejich parametry, lze v programovacím jazyku Racket vytvářet a následně i volat funkce s proměnným počtem parametrů, což může být v některých případech velmi užitečné. V nejjednodušším případě, pokud mají být všechny parametry proměnné (tj. ve skutečnosti se anonymní funkce nemusí volat s parametrem žádným) se používá následující způsob vytvoření anonymní funkce:
(lambda [jméno jediného formálního parametru] [tělo anonymní funkce])
To tedy znamená, že mezi následujícími dvěma výrazy je poměrně velký rozdíl:
(lambda (x) ...) (lambda y ...)
Při volání druhé výše uvedené anonymní funkce se do formálního parametru y předá seznam obsahující všechny skutečně předávané parametry. S tímto seznamem je možné pracovat jako s kterýmkoli jiným seznamem, tj. například lze procházet přes jeho prvky atd:
; jeden ze způsobů vytvoření seznamu ((lambda x x) 1 2 3 4) '(1 2 3 4) ; součet hodnot všech předaných parametrů ; (apply bude popsána dále) ((lambda x (apply + x)) 1 2 3 4) 10 ; na parametr (seznam) lze aplikovat různé funkce ((lambda x (length x)) 'a 'b 'c 'd) 4
V programovacím jazyku Racket lze též použít kombinaci obou předchozích způsobů, tj. vytvoření anonymní funkce vyžadující pevný počet povinných parametrů s tím, že všechny ostatní hodnoty předané anonymní funkci jsou nepovinné. Všechny nepovinné hodnoty jsou při volání anonymní funkce uloženy do seznamu přiřazeného poslednímu parametru, přičemž tento parametr musí být při definici anonymní funkce od ostatních parametrů oddělen tečkou. Povšimněte si, že se v tomto případě nejedná o nějakou speciální syntaxi, kterou bylo nutné do jazyka zavést, ale pouze o využití již existujících možností Racketu, které podporuje, podobně jako LISP, explicitní zápis tečka-dvojic:
(lambda ([formální parametry].poslední parametr) [tělo anonymní funkce])
Následují příklady použití anonymní funkce s několika povinnými (pojmenovanými) parametry a možností předání dalších hodnot v seznamu předanému poslednímu parametru. Ve všech příkladech se v těle anonymní funkce pouze vytiskne obsah posledního „seznamového“ parametru:
((lambda (a . b) b) 1 2 3 4) '(2 3 4) ((lambda (a b . c) c) 1 2 3 4) '(3 4) ((lambda (a b c . d) d) 1 2 3 4) '(4) ((lambda (a b c d . e) e) 1 2 3 4) '()
((lambda (a . b) b) 1 2 3 4) (2 3 4) ((lambda (a b . c) c) 1 2 3 4) (3 4) ((lambda (a b c . d) d) 1 2 3 4) (4) ((lambda (a b c d . e) e) 1 2 3 4) ()
10. Pojmenované funkce s proměnným počtem parametrů
Vzhledem k tomu, že speciální formu define (ve variantě, kdy se definuje funkce) lze kdykoli zapsat s využitím speciální formy lambda, je v programovacím jazyku Racket možné nadefinovat pojmenovanou funkci akceptující proměnný (tj. v krajním případě i nulový) počet parametrů, z nichž je při volání funkce automaticky vytvořen seznam, se kterým je možné v těle funkce libovolným způsobem manipulovat. Syntakticky vypadá definice takové funkce následovně:
(define (jméno funkce . parametr) [tělo funkce])
Což je ekvivalentní zápisu, který již známe z předchozího textu:
(define jméno funkce (lambda parametr [tělo funkce]))
Následuje příklad definice funkce s proměnným počtem parametrů:
; funkce vracející počet skutečně předaných parametrů (define (foo . parametry) (length parametry))
Zavolání této funkce bez parametrů vrátí nulu:
(foo) 0
Předat můžeme jeden parametr:
(foo 42) 1
A samozřejmě i větší počet parametrů:
(foo 1 2) 2 (foo "bar" "baz") 2 (foo '(1 2 3 4)) 1
Ukažme si ještě alternativní formu zápisu využívající kombinace define a lambda:
; alternativní forma zápisu (define foo (lambda parametry (length parametry))) ; volání funkce bez parametrů (foo) 0 ; volání funkce se třemi parametry (zde se jedná o trojici symbolů) (foo 'a 'b 'c) 3
11. Povinné a nepovinné parametry anonymních funkcí
Při deklaraci anonymních funkcí můžeme použít i takzvané nepovinné parametry. Pokud se při volání anonymní funkce neuvede hodnota takového parametru, bude za ni dosazena výchozí hodnota. Nepovinné parametry se poznají snadno – jsou zapsány formou vektoru o dvou prvcích. Prvním prvkem vektoru je jméno parametru, druhým prvkem pak výchozí hodnota nepovinného parametru.
Příklad anonymní funkce s jediným parametrem, který je nepovinný a jehož výchozí hodnota je rovna dvěma:
(lambda ([parametr 2]) ...tělo anonymní funkce...)
Příklad anonymní funkce s jedním povinným parametrem a jedním parametrem nepovinným:
(lambda (parametr-1 [parametr-2 2]) ...tělo anonymní funkce...)
Příklad anonymní funkce se dvěma nepovinnými parametry:
(lambda ([parametr-1 100] [parametr-2 200]) ...tělo anonymní funkce...)
V další ukázce je deklarována funkce inc zvyšující hodnotu svého (povinného) parametru buď o jedničku nebo o uvedenou nepovinnou hodnotu delta:
#lang racket/base (define inc (lambda (x [delta 1]) (+ x delta))) (display (inc 10)) (newline) (display (inc 10 20)) (newline) (display ((lambda (x [delta 1]) (+ x delta)) 10)) (newline) (display ((lambda (x [delta 1]) (+ x delta)) 10 20)) (newline)
Výsledky:
11 30 11 30
12. Povinné a nepovinné parametry pojmenovaných funkcí
Podobně, jako u lambda výrazů, je možné povinné a nepovinné parametry použít i při deklaraci běžných pojmenovaných funkcí. Příklad z předchozí kapitoly, v němž jsme definovali funkci inc, tedy můžeme velmi snadno přepsat takto:
#lang racket/base (define (inc x [delta 1]) (+ x delta)) (display (inc 10)) (newline) (display (inc 10 20)) (newline)
S výsledky:
11 30
Následuje poněkud složitější (a možná i praktičtější) příklad, v němž je deklarována funkce pro výpočet lineární transformace. Tato funkce akceptuje jeden povinný parametr x a dále dvojici nepovinných parametrů, které představují měřítko (hodnotu změny měřítka) a offset (posun). Výchozí hodnota měřítka je 1 (identita) a výchozí hodnota posunu je 0 (bez posunu):
#lang racket/base (define (transform x [scale 1] [offset 0]) (+ offset (* x scale))) (display (transform 10)) (newline) (display (transform 10 20)) (newline) (display (transform 10 20 -50)) (newline)
Opět si ukažme výsledky použití této funkce:
10 200 150
13. Parametry anonymních funkcí explicitně specifikované svým jménem
Kromě povinných a nepovinných parametrů, popř. volitelného počtu parametrů existují ještě další způsoby, jakými je možné funkcím předávat hodnoty, které mají funkce zpracovávat. Jednou z dalších možností jsou takzvané keywords parametry, což jsou parametry s explicitně specifikovaným jménem.
V dalším demonstračním příkladu se opět setkáme s funkcí určenou pro výpočet lineární transformace. Tentokrát jsou ovšem parametry s měřítkem a offsetem (posunem) deklarovány takovým způsobem, že je nutné je specifikovat přímo svým jménem, které začíná křížkem a dvojtečkou:
#lang racket/base (define transform (lambda (x #:scale scale #:offset offset) (+ offset (* x scale))))
Příklad použití:
(display (transform 10 #:offset 0 #:scale 1)) (newline) (display (transform 10 #:offset -100 #:scale 1)) (newline) (display (transform 10 #:offset -100 #:scale 100)) (newline)
Mnohem praktičtější je však kombinace obou předchozích možností – parametrů nepovinných a současně specifikovaných svým jménem. I to je v jazyku Racket pochopitelně možné, a to následujícím způsobem:
(define transform (lambda (x #:scale [scale 1] #:offset [offset 0]) (+ offset (* x scale))))
Popř. pro větší názornost:
(define transform (lambda (x #:scale [scale 1] #:offset [offset 0]) (+ offset (* x scale))))
Příklad použití:
(display (transform 10 #:offset 0 #:scale 1)) (newline) (display (transform 10)) (newline) (display (transform 10 #:offset -10)) (newline) (display (transform 10 #:offset -100 #:scale 1)) (newline) (display (transform 10 #:offset -100 #:scale 100)) (newline)
14. Parametry pojmenovaných funkcí specifikované jménem
Tato kapitola bude velmi stručná, protože i u pojmenovaných funkcí je možné specifikovat parametry, které se při volání funkce musí uvádět společně se svým jménem. Následuje tedy ekvivalent prvního příkladu z předchozí kapitoly:
#lang racket/base (define (transform x #:scale scale #:offset offset) (+ offset (* x scale))) (display (transform 10 #:offset 0 #:scale 1)) (newline) (display (transform 10 #:offset -100 #:scale 1)) (newline) (display (transform 10 #:offset -100 #:scale 100)) (newline)
Taktéž můžeme vytvořit funkci akceptující nepovinné a současně i pojmenované parametry:
#lang racket/base (define (transform x #:scale [scale 1] #:offset [offset 0]) (+ offset (* x scale))) (display (transform 10 #:offset 0 #:scale 1)) (newline) (display (transform 10)) (newline) (display (transform 10 #:offset -10)) (newline) (display (transform 10 #:offset -100 #:scale 1)) (newline) (display (transform 10 #:offset -100 #:scale 100)) (newline)
Výsledek předchozího skriptu:
10 10 0 -90 900
15. Pojmenované a nepojmenované funkce s různou aritou
Po přečtení předchozích sedmi kapitol by se mohlo zdát, že rozdíl mezi pojmenovanými a anonymními funkcemi je pouze nepatrný a spočívá v tom, že u pojmenovaných funkcí je nějakému symbolu funkce přiřazena a že tento symbol tedy funkci reprezentuje při jejím volání. Ve skutečnosti jsou však možnosti anonymních funkcí nepatrně větší a to z toho důvodu, že je možné vytvořit anonymní funkci s různou aritou. Ve skutečnosti se jedná o větší počet současně deklarovaných funkcí, které mají (mohou mít) různá těla podle toho, kolik parametrů se při volání funkce použije.
Podívejme se na příklad funkce, která akceptuje různý počet parametrů – od žádného parametru do dvou parametrů. Pro každou variantu je ve skutečnosti použito jiné tělo (tedy z pohledu interpretru naprosto odlišný kód):
#lang racket/base (define inc (case-lambda [() 0] [(x) (+ x 1)] [(x delta) (+ x delta)]))
Příklad použití této multifunkce:
(display (inc)) (newline) (display (inc 10)) (newline) (display (inc 10 -1)) (newline)
(defn multiply ([x] (* x x)) ([x y] (* x y)) ([x y z] (* x y z)))
16. Funkce jako hodnoty
V programovacím jazyku Racket jsou funkce plnohodnotnými objekty, takže je například můžeme navázat na další symboly („uložit do proměnné“) atd. Ukažme si několik jednoduchých příkladů:
> (define plus +) > (define add plus) > (+ 1 2) 3 > (add 1 2) 3 > (plus 1 2) 3 > (add 1 2 3 4) 10
Funkce lze použít jako parametr jiné funkce (funkce vyššího řádu):
> (apply + '(1 2 3)) 6 > (define plus +) > (apply plus '(1 2 3)) 6
Vytvoření nové funkce s využitím compose (podobné threading makru z Clojure):
> ((compose1 - sqr) 10) -100 > ((compose1 sqr - sqr) 10) 10000
17. Obsah následující části seriálu
V navazující části seriálu o světě lispovských programovacích jazyků si ukážeme některé pokročilejší možnosti tohoto jazyka a především pak knihovny, které je možné ihned po instalaci Racketu použít. Jako ukázku si uvedeme program pro výpočet a vykreslení Mandelbrotovy množiny. Tento příklad byl získán ze stránky projektu Rosetta Code. V tomto příkladu je ukázáno použití knihovny pro práci s rastrovou grafikou, vytvoření rastrového obrázku ve formátu PNG, použití formy for* pro vytvoření zanořených programových smyček atd.:
#lang racket (require racket/draw) (define (iterations a z i) (define z′ (+ (* z z) a)) (if (or (= i 255) (> (magnitude z′) 2)) i (iterations a z′ (add1 i)))) (define (iter->color i) (if (= i 255) (make-object color% "black") (make-object color% (* 5 (modulo i 15)) (* 32 (modulo i 7)) (* 8 (modulo i 31))))) (define (mandelbrot width height) (define target (make-bitmap width height)) (define dc (new bitmap-dc% [bitmap target])) (for* ([x width] [y height]) (define real-x (- (* 3.0 (/ x width)) 2.25)) (define real-y (- (* 2.5 (/ y height)) 1.25)) (send dc set-pen (iter->color (iterations (make-rectangular real-x real-y) 0 0)) 1 'solid) (send dc draw-point x y)) (send target save-file "mandelbrot.png" 'png)) (mandelbrot 300 200)

Obrázek 5: Výsledek výpočtu provedeného předchozím skriptem.
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
- Beautiful Racket: an introduction to language-oriented programming using Racket
https://beautifulracket.com/ - Stránky projektu Racket
https://racket-lang.org/ - Dokumentace k projektu Racket
https://docs.racket-lang.org/index.html - Seznam dostupných balíčků pro Racket
https://pkgs.racket-lang.org/ - Racket na Wikipedii
https://en.wikipedia.org/wiki/Racket_(programming_language) - Blogy o Racketu a navazujících technologiích
https://blog.racket-lang.org/ - Prográmky psané v Racketu na RosettaCode
http://rosettacode.org/wiki/Category:Racket - 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/ - Tail call (a její optimalizace)
https://en.wikipedia.org/wiki/Tail_call - 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 - 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 - The JavaTM Virtual Machine Specification, Second Edition
http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html - The class File Format
http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html - javap – The Java Class File Disassembler
http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/javap.html - javap-java-1.6.0-openjdk(1) – Linux man page
http://linux.die.net/man/1/javap-java-1.6.0-openjdk - Using javap
http://www.idevelopment.info/data/Programming/java/miscellaneous_java/Using_javap.html - Examine class files with the javap command
http://www.techrepublic.com/article/examine-class-files-with-the-javap-command/5815354