Obsah
1. Jemný úvod do rozsáhlého světa jazyků LISP a Scheme
2. Stručná historie vzniku programovacího jazyka LISP
4. Vznik interaktivní smyčky REPL
6. Rozsáhlý a chaotický svět dialektů programovacího jazyka LISP
7. LISP jako koncept, nikoli konkrétní dialekt
8. Již popsané dialekty a implementace LISPu a Scheme
16. Další programovací jazyky inspirované LISPem
1. Jemný úvod do rozsáhlého světa jazyků LISP a Scheme
„A computer without COBOL and FORTRAN is like a piece of chocolate cake without ketchup or mustard.“
Svět LISPovských jazyků je dnes velmi rozsáhlý a poměrně nepřehledný, ovšem není se čemu divit, protože první koncept LISPu vznikl již před neuvěřitelnými 61 lety, konkrétně v roce 1958. Jedná se tedy o jeden z prvních vyšších programovacích jazyků vyvinutých pro nasazení na mainframech. Některé z těchto jazyků jsou (s modifikacemi a vylepšeními) používány dodnes, a to nikoli pouze z důvodu konzervativnosti programátorů či nutnosti údržby starého programového kódu stále používaného v produkčním prostředí. V LISPu se totiž objevilo hned několik zajímavých a přelomových konceptů, které samy o sobě dokázaly udržet tento programovací jazyk v hledáčku programátorů. A nejenom to – mnoho myšlenek z LISPu se postupně uplatňuje i v dalších programovacích jazycích, i když je nutné říci, že některé koncepty (homoikonicita a s ní související makra a metaprogramování) jsou do mnoha dalších jazyků přenositelná jen s obtížemi (poměrně úspěšné jsou v tomto ohledu jazyky Rust a Julia se svými systémy maker).
Obrázek 1: Originální manuál k první verzi FORTRANu určeného pro mainframy IBM 704 (FORTRAN je schválně psán velkými písmeny).
2. Stručná historie vzniku programovacího jazyka LISP
„With Lisp, McCarthy did for programming something like what Euclid did for geometry.“
Paul Graham
Syntaxe jazyka LISP je již po šedesát let zdrojem inspirace pro autory vtipů
Historie programovacího jazyka LISP je velmi dlouhá, neboť se jedná (jak již víme) o jeden z nejstarších vyšších programovacích jazyků vůbec. Autorem teoretického návrhu tohoto jazyka je John McCarthy, který se již v roce 1956 připojil k týmu, jehož úkolem bylo navrhnout algebraický programovací jazyk umožňující mj. zpracování seznamů, jenž by byl vhodný pro vývoj systémů umělé inteligence – AI (zatímco dnes jsou „v kurzu“ enterprise systémy popř. kontejnerizace a mikroslužby, v padesátých a šedesátých letech minulého století se jednalo o umělou inteligenci a expertní systémy). McCarthy navrhl, aby fakta o okolním světě (která může AI při své činnosti použít) byla reprezentována formou vět ve vhodně strukturovaném formálním jazyce. Posléze se ukázalo, že je výhodné reprezentovat jednotlivé věty formou rekurzivně zanořených seznamů. McCarthy však myšlenku jazyka vhodného pro AI rozpracoval ještě dále – odklonil se například od infixové notace zápisu algebraických výrazů, protože naprogramování některých manipulací s těmito výrazy (derivace, integrace, zjednodušení výrazů, logická dedukce) bylo zbytečně složité. Navíc jím navržená prefixová notace do značné míry odpovídala zápisu výrazů v lambda kalkulu, jehož teorii vytvořil Alonzo Church.
Obrázek 2: Na tomto grafu evoluce programovacích jazyků můžeme vidět některé historicky významné programovací jazyky, s nimiž jsme se již setkali v seriálu o historii počítačů. Jedná se zejména o Fortran, Cobol, SNOBOL, Algol, APL, BASIC (resp. přesněji řečeno celá rodina jazyků nesoucích toho jméno) a samozřejmě taktéž o LISP a jeho varianty.
Následně McCarthy ve svých teoretických pracích (vznikajících v průběhu let 1957 a 1958) ukázal, že je možné pomocí několika poměrně jednoduchých operací (a notací pro zápis funkcí) vytvořit programovací jazyk, který je Turingovsky kompletní (tj. jeho výpočetní mocnost je ekvivalentní Turingovu stroji), ale zápis algoritmů v tomto jazyce je mnohem jednodušší než zápis pravidel pro Turingův stroj. Tento jazyk, jenž byl z velké části založen na Lambda kalkulu, obsahoval možnost vytváření rekurzivních funkcí (což byl významný rozdíl například oproti tehdejší verzi FORTRANU), umožňoval použít funkce jako argumenty jiných funkcí, dále podporoval podmíněné výrazy (jedna z variant speciální formy), funkce pro manipulaci se seznamy a v neposlední řadě také funkci eval, o níž se zmíníme ve čtvrté kapitole.
Obrázek 3: Alonzo Church, autor slavného lambda kalkulu.
V pracích McCarthyho se objevily i některé (v té době nové) jazykové konstrukce, které dnes nalezneme v prakticky všech vyšších programovacích jazycích. Zejména se to týká konstrukce IF s pravdivostním výrazem, která je v LISPu reprezentovaná speciální formou stejného jména (typicky se dnes ovšem zapisuje malými písmeny, tedy if), popř. rozšířenou variantou cond. Oproti původnímu „aritmetickému IF“ z FORTRANu bylo možné jak pravdivostní výraz, tak i obě větve zapsat formou dalšího (rekurzivně vyhodnocovaného) výrazu.
Obrázek 4: John McCarthy.
První teoretický návrh LISPu byl pojat skutečně minimalisticky. Nalezneme v něm pouhých sedm funkcí a speciálních forem, z nichž některé byly později přejmenovány. Pro úplnost do tabulky dodávám i speciální formu quote, která byla v původním článku o LISPu popsána slovně (v M-výrazech – viz další text – ji není nutné přímo použít):
# | Typ | Původní označení | Jméno v LISPu 1.0 i dalších derivátech |
---|---|---|---|
1 | funkce (predikát) | null | null/nullp/null? |
2 | funkce (predikát) | atom | atom |
3 | funkce (predikát) | p1==p2 | eq |
4 | funkce | combine | cons |
5 | funkce | first | car |
6 | funkce | rest | cdr |
7 | speciální forma | if | cond |
8 | speciální forma | popsáno slovně | quote/' |
3. LISP a umělá inteligence
„The default language, embodied in a succession of popular languages, has gradually evolved toward Lisp.“
Paul Graham
V předchozí kapitole bylo mj. uvedeno i často opakované tvrzení, že LISP byl programovací jazyk vytvořený převážně pro potřeby studia a implementace umělé inteligence (AI – Artifical Intelligence). Toto tvrzení má sice reálný základ, ale není zcela pravdivé. Reálný základ spočívá v tom, že McCarthy je jak ideovým tvůrcem LISPu, tak i člověkem, který termín „umělá inteligence“ vytvořil a použil pro pojmenování několikatýdenní konference (spíše workshopu) nazvané Darthmouth Summer Research Project on Artificial Intelligence.
A právě na této konferenci si McCarthy začal zahrávat s myšlenkou na vytvoření nového programovacího jazyka, který byl inspirován jazykem IPL (Information Processing Language) autorů Newell, Shaw, Simon a jeho schopnostmi práce se seznamy (ve skutečnosti byl IPL vytvořen jako sada maker pro assembler, tj. jednalo se o dosti primitivní a vlastně i nízkoúrovňovou záležitost). Později se LISP skutečně pro výzkum AI používal, ale nikoli proto, že by byl primárně určen pro umělou inteligenci, ale protože jak vývoj LISPu, tak i primární výzkum AI probíhal na stejné universitě, konkrétně na slavném MITu (navíc nic lepšího než LISP nevzniklo, až do první verze Prologu v roce 1972). Spojení LISPu s AI ovšem bylo samotnému programovacímu jazyku spíše na škodu, protože si ho mnozí programátoři spojovali se „slonovinovou věží“ univerzitního prostředí a navíc – velká očekávání, která již na konci padesátých let mnozí do AI vkládali, se nesplnila, což jak samotnému oboru, tak i nepřímo LISPu uškodilo.
Obrázek 5: Hra Abuse je z velké části napsána v LISPu – nízkoúrovňové části používají nativní knihovny (na Linuxu například SDL), ovšem veškerá herní logika je skutečně v LISPu a s troškou vůle a volného času lze z Abuse vytvořit zcela odlišnou hru. Zdánlivá malá výkonnost LISPu se zde neprojevuje, protože Abuse lze bez problémů hrát i na stařičkém počítači s mikroprocesorem 80486DX2 (ostatně nízká výkonnost LISPu je pro mnoho jeho implementací spíše legendou, než faktem).
4. Vznik interaktivní smyčky REPL
Na McCarthovu původně pouze teoretickou práci navázal S. R. Russell, který si uvědomil, že samotná funkce eval navržená McCarthym, pokud by byla skutečně implementována na nějakém počítači, může sloužit jako základ plnohodnotného interpretru jazyka LISP (interpret LISPu se někdy též označuje zkratkou REPL: Read-Eval-Print-Loop, tj. interpretr ve smyčce načítá jednotlivé výrazy, vyhodnocuje je a následně tiskne jejich výslednou hodnotu). Russell skutečně celou smyčku REPL implementoval – tímto způsobem se zrodila první reálně použitelná verze LISPu.
Obrázek 6: Základem smyčky REPL je funkce EVAL. Zde je uveden prakticky celý její zdrojový kód získaný z dvoustránkové publikace o LISPu napsané McCarthym. Na první straně je popsán celý jazyk (jeho syntaxe i sémantika), stranu druhou zabírá právě výpis funkce EVAL.
Obrázek 7: Ovládací panel mainframu IBM System/360 Model 65. Tento snímek zde uvádím především z toho důvodu, aby bylo zřejmé, že pod pojmem „interaktivita“ se v oblasti IT může skrývat mnoho pojmů. Dnes si interaktivní smyčku můžeme představit snadno – jedná se o terminál či o notebook (IPython), který ihned reaguje na příkazy zapisované uživateli. Ovšem v dobách prvních dvou generací mainframů byly vstupně-výstupní prostředky mnohem více omezené, takže výstup byl provádět na tiskárnu a vstupem býval dálnopis nebo jeho specializovaná obdoba. A pro administrátory taktéž zde zobrazený ovládací panel.
Obrázek 8: Koncept diáře (notebooku) je použit například v nástroji nazvaném Gorilla REPL, který mohou využít programátoři pracující s jazykem Clojure. Na diář se můžeme dívat jako na vylepšenou variantu interaktivní smyčky REPL, která je „dvourozměrná“ (diář zobrazuje historii, umožňuje se v ní vracet zpět, provádět změny apod.).
5. M-výrazy a S-výrazy
McCarthy a jeho kolektiv se při vývoji LISPu inspirovali kromě jiného i v té době již existujícím programovacím jazykem FORTRAN, což je možná poněkud překvapivé, ovšem musíme si uvědomit, že FORTRAN byl v té době jedním z mála vyšších programovacích jazyků (mezi další patří například FLOW-MATIC firmy Sperry-Rand, Commercial Translator firmy IBM a AIMACO (Air Material Command), což jsou ideoví předchůdci COBOLu). Mezi přednosti FORTRANu patřil i jednoduchý zápis aritmetických výrazů, což je ostatně i základ významu zkratky FORTRAN (FORMula TRANslating System/FORMula TRANslator). Původně měl LISP umožňovat běžný infixový zápis aritmetických výrazů, ovšem v první verzi se tato možnost neobjevila a ani nikdy později se nestala součástí mainstreamových LISPů. Navíc byl zápis LISPovských programů v původním návrhu jazyka odlišný od formy, kterou známe dnes. Používaly se totiž takzvané M-výrazy (M-expressions), v nichž se namísto kulatých závorek zapisovaných okolo všech forem (funkcí, speciálních forem, maker) používaly závorky hranaté, ovšem použité pouze u parametrů. Zápis byl tedy bližší spíše dnešním programovacím jazykům (i když byl méně systematický).
Obrázek 9: První oficiální publikace o jazyku LISP. Právě v ní se objevují M-výrazy.
Interně se měly M-výrazy překládat na takzvané S-výrazy (S-expressions), které přetrvaly dodnes a vizuálně odlišují programy psané v LISPu či Scheme od prakticky všech ostatních programovacích jazyků. S-výrazy již dokážou popsat samotný program formou (rekurzivních) seznamů, tj. programy jsou reprezentovány stejným způsobem, jako samotná data. Této důležité vlastnosti se říká homoikonicita (homoiconicity). První funkční verze LISPu ovšem přímo M-výrazy nedokázala zpracovat; překlad byl prováděn ručně s tím, že v další verzi LISPu již bude překladač M-výrazů naprogramován. Mezitím se ovšem zjistilo, že S-výrazy, i přes poněkud neobvyklý zápis, jsou velmi užitečné a výkonné. Navíc je bylo možné na klávesnici počítače IBM 704 zapisovat snadněji, než programy s hranatými závorkami, takže výsledkem je stav, který vydržel celých šedesát let – programy psané v LISPu jsou zapisovány s využitím S-výrazů, samozřejmě s tím, že pomocí maker lze význam (sémantiku) zapisovaných forem měnit.
Obrázek 10: První strana dvoustranného článku s popisem jazyka LISP i jeho interpretru (napsaného taktéž v LISPu).
6. Rozsáhlý a chaotický svět dialektů programovacího jazyka LISP
V průběhu dalších více než pěti desetiletí dosti překotného rozvoje výpočetní techniky i programovacích jazyků vzniklo velmi mnoho dialektů tohoto programovacího jazyka, například MacLISP, InterLISP, ZetaLISP, XLisp, AutoLISP (původně odvozený z XLispu), samozřejmě Emacs LISP nebo slavný Common LISP (více viz odkazy na konci článku). Kromě těchto implementací jazyka LISP, které se od sebe v několika ohledech odlišují (například existencí či neexistencí maker či objektového systému), vznikl v minulosti i nový dialekt tohoto jazyka nazvaný Scheme (původně Schemer), jehož autory jsou Guy L. Steele a Gerald Jay Sussman (Steele později pracoval na specifikaci Javy i programovacího jazyka Fortress). Tento dialekt je implementačně jednodušší a také se ho lze naučit rychleji, než mnohé další varianty jazyka LISP (jedna implementace Scheme se jmenuje Scheme 48, protože byla naprogramována za 48 hodin, nyní toto číslo znamená, že se programátor dokáže Scheme naučit za 48 hodin).
Obrázek 12: Vývoj některých dialektů Lispu.
Zdroj: Wikipedia.
Právě z těchto důvodů se Scheme využívá či využívalo jak při výuce programování, tak i v mnoha open-source projektech, například v grafickém editoru GIMP jako jeden z podporovaných skriptovacích jazyků. Richard Stallman si dokonce přál, aby se Scheme (přesněji jeho GNU implementace Guile) stalo standardním skriptovacím jazykem většiny GNU aplikací, což je idea, která se – především po vzniku dalších vysokoúrovňových programovacích jazyků (Perl, Python, TCL) – nakonec neuskutečnila (i když vedla k tzv. Tcl war).
7. LISP jako koncept, nikoli konkrétní dialekt
Musíme si však uvědomit, že samotný LISP je nutné chápat jako spíše koncept, než konkrétní programovací jazyk. Proto můžeme pod pojmem LISP (psáno též Lisp) najít poměrně velké množství programovacích jazyků, které sice mají podobný základ, ovšem konkrétní implementace jsou značně rozdílné. Do rodiny LISPovských jazyků tak dnes patří i dosti odlišné jazyky, jako například Clojure a výše zmíněné implementace jazyka Scheme. Dnes patří mezi nejpopulárnější implementace LISPovského jazyka především Common Lisp, dále pochopitelně Emacs Lisp, ovšem nesmíme zapomenout na již zmíněné Clojure a taktéž Racket neboli původním názvem PLT Scheme popř. na GNU Guile (implementace Scheme, která měla být původně určena jako základní rozšiřující jazyk v GNU projektu, viz zmínka o RMS v předchozí kapitole).
Velmi pěkně jsou základní společné vlastnosti a rozdíly mezi těmito jazyky shrnuty na stránce Common Lisp, Racket, Clojure, Emacs Lisp.
Obrázek 13: Mnohé první pokusy o umělou inteligenci používaly právě LISP (zde algoritmus pro nalezení cesty v dvourozměrném světě implementovaný na počítačích společnosti Symbolics.
8. Již popsané dialekty a implementace LISPu a Scheme
Na stránkách Rootu i serveru Mojefedora.cz jsme se již setkali s relativně velkým množstvím dialektů jazyka LISP či Scheme. Tyto dialekty budou (samozřejmě jen ve stručnosti) představeny v navazujících kapitolách.
Obrázek 14: SICP – jedna z nejznámějších knížek (nejenom) o LISPovských jazycích.
9. Scheme
Prvním důležitým jazykem odvozeným od LISPu je pochopitelně jazyk nazvaný Scheme. Původními autory programovacího jazyka Scheme jsou Guy Lewis Steele a Gerald Jay Sussman (Steele and Sussman, někdy též zkracováno na S and S), kteří v době návrhu tohoto jazyka pracovali ve slavném Massachussetském technologickém institutu (MIT), který již byl zmíněn v předchozích kapitolách. První verze jazyka Scheme byla v průběhu roku 1975 naprogramována v samotném LISPu, konkrétně v MacLispu. Název tohoto dialektu programovacího jazyka LISP ovšem nemá nic společného s počítači firmy Apple, jednalo se o verzi LISPu vytvořenou taktéž na MIT, která byla původně určena pro počítače PDP-10 a operační systém Multics.
Obrázek 15: Jedna z mnoha knih o jazyce Scheme.
Guy Steele spolu s Geraldem Sussmanem chtěli nový jazyk použít pro zkoumání vlastností takzvaných aktorů, které se v dnešní době, tj. necelých 45 let po vzniku jazyka Scheme, opět těší zvýšenému zájmu vědců i programátorů, především díky stále většímu důrazu na tvorbu systémů, v nichž je spouštěno velké množství paralelně běžících a vzájemně kooperujících procesů (aktory je možné považovat za speciální formu uzávěrů – closures, ostatně právě nutnost podpory uzávěrů ve Scheme poměrně zásadně ovlivnilo jeho návrh, zejména odlišný způsob určování rozsahu platnosti objektů).0
Výsledkem jejich snahy byl v mnoha ohledech minimalistický programovací jazyk podporující různá paradigmata programování, ovšem zaměřený především na paradigma funkcionální. Původně se tento nový programovací jazyk jmenoval SCHEMER, ovšem systém souborů používaný operačním systémem ITS na PDP-10, na němž byly uloženy zdrojové kódy původního interpretru, omezoval délku názvů na šest znaků, takže se postupně název zkrátil ze SCHEMER a dnešní Scheme. Oba autoři následně zveřejnili popis syntaxe a především sémantiky nového programovacího jazyka v sérii článků, které se dnes souhrnně nazývají „Lambda Papers“.
Články s podrobnějšími informacemi o jazyku Scheme:
- Scheme: kostlivec ve skřini nebo nehasnoucí hvězda?
- '(Programovací (cons 'jazyk 'Scheme))
- Programovací jazyk Scheme: definice anonymních i pojmenovaných funkcí, iterace
- Základy programování v jazyku Scheme
- Scheme vs. Prolog
10. Clojure
Samozřejmě nesmíme zapomenout ani na programovací jazyk Clojure, který tvoří dnes již samostatnou vývojovou odnož LISPovského jazyka. Clojure byl původně jazyk určený pro běh nad virtuálním strojem Javy, tj. JVM (Java Virtual Machine), ovšem později vznikla i jeho varianta pro .NET a taktéž transpiler pro převod programů do JavaScriptu – tím je mj. umožněn běh aplikací psaných v Clojure v prohlížečích a v Node.js. V jazyku Clojure se objevují některé nové a užitečné koncepty, které jsou namířeny praktickým směrem, na rozdíl od spíše akademicky pojatých variant jazyka Scheme. Na první pohled je patrný odlišný způsob deklarace funkcí, kdy se parametry zapisují do hranatých závorek a jsou tak vizuálně odlišeny od ostatního kódu (počet formálních parametrů je konstantní, takže použití hranatých závorek vyhrazených pro vektory je zcela logické):
(defn csv-data->maps "Convert read CSV data into proper Clojure map." [csv-data] (map zipmap (->> (first csv-data) ;; header (map keyword) ;; heder items -> keywords repeat) (rest csv-data)))
Podobně byl zjednodušen zápis generátorové notace seznamu, jejíž čitelná podoba vypadá takto:
(zipmap dates-from (for [date dates-from] (let [full-filename (str data-directory "/" date "/" filename)] (load-csv full-filename))))
Zmenšil se i počet závorek ve formě cond, která je mnohem více čitelná a do značné míry redukuje „závorkové peklo“, kterými je LISP známý:
(defn -main "Entry point to the Chainring service." [& args] (let [all-options (cli/parse-opts args cli-options) options (all-options :options)] ; perform the selected operation according to CLI options (cond (:help options) (show-help all-options) (:print-config options) (show-configuration configuration) :else (start-server))))
Zajímavější je ovšem zcela odlišné chápání pojmu „proměnné“ a „hodnoty“ v programovacím jazyce Clojure. Rozlišuje se totiž mezi několika různými způsoby, jakými je možné změnit hodnotu v proměnné. Změna stavu proměnných (označovaných jako identity, protože se od běžných proměnných odlišují) totiž může být provedena buď koordinovaně či naopak zcela nezávisle na ostatních identitách. Koordinovaná změna stavu více identit je prováděna uvnitř transakcí, tj. konkrétně s využitím objektů typu ref. Změna, resp. změny stavů identit se taktéž odlišují v tom, že mohou být provedeny buď synchronně či asynchronně – opět v závislosti na potřebách konkrétní vyvíjené aplikace. Synchronní změna stavu identit je provedena ihned a tudíž přímo ve vláknu, které tuto změnu provádí (synchronní a současně i nezávislá změna stavu identity je tedy z hlediska vývojáře prakticky totožná se změnou hodnoty proměnné). Naopak asynchronní změna stavu identit(y) nemusí být provedena ihned, ale někdy v blíže neurčené budoucnosti. To znamená, že asynchronní změnu je možné implementovat v jiném vlákně.
V programovacím jazyce Clojure z tohoto důvodu existují čtyři typy referencí, přesněji řečeno čtyři takzvané referenční typy. Reference vždy ukazují na neměnná data, protože filozofie jazyka Clojure je založena nikoli na jednoduché změně obsahu proměnných (či změně stavu objektů – tj. jejich atributů, pokud budeme uvažovat i o objektově orientovaných jazycích), ale na takzvaných identitách asociovaných s různými stavy, které se v různých časových okamžicích běžícího programu mohou lišit. Samotný stav je představován neměnnou (immutable) hodnotou, což však neznamená, že by reference po celou dobu běhu programu musela odkazovat na stejný stav. Reference totiž může být přesměrována na jinou neměnnou hodnotu – zkráceně budeme říkat, že se změnila hodnota reference, i když je to poněkud nepřesné. Zmíněné čtyři typy referencí použitých v programovacím jazyku Clojure se od sebe odlišují především v tom, zda je změna hodnot referencí synchronní či asynchronní a zda je realizována koordinovaně (tj. v transakci) či nezávisle na změně hodnot ostatních referencí.
Všechny čtyři podporované referenční typy jsou vypsány v následující tabulce:
Jméno | Var | Ref | Atom | Agent |
---|---|---|---|---|
Změna stavu | synchronní | synchronní | synchronní | asynchronní |
Typ změny | lokální, v rámci jednoho vlákna | koordinovaná | nezávislá | nezávislá |
Podpora transakcí | ne | ano | ne | ne |
Články s podrobnějšími informacemi o programovacím jazyku Clojure:
- Clojure 1: Úvod
- Clojure 2: Symboly, kolekce atd.
- Clojure 3: Funkcionální programování
- Clojure 4: Kolekce, sekvence a lazy sekvence
- Clojure 5: Sekvence, lazy sekvence a paralelní programy
- Clojure 6: Podpora pro paralelní programování
- Clojure 7: Další funkce pro paralelní programování
- Clojure 8: Identity, stavy, neměnné hodnoty a reference
- Clojure 9: Validátory, pozorovatelé a kooperace s Javou
- Clojure 10: Kooperace mezi Clojure a Javou
- Clojure 11: Generátorová notace seznamu/list comprehension
- Clojure 12: Překlad programů z Clojure do bajtkódu JVM I:
- Clojure 13: Překlad programů z Clojure do bajtkódu JVM II:
- Clojure 14: Základy práce se systémem maker
- Clojure 15: Tvorba uživatelských maker
- Clojure 16: Složitější uživatelská makra
- Clojure 17: Využití standardních maker v praxi
- Clojure 18: Základní techniky optimalizace aplikací
- Clojure 19: Vývojová prostředí pro Clojure
- Clojure 20: Vývojová prostředí pro Clojure (Vimu s REPL)
- Clojure 21: ClojureScript aneb překlad Clojure do JS
- Leiningen: nástroj pro správu projektů napsaných v Clojure
- Leiningen: nástroj pro správu projektů napsaných v Clojure (2)
- Leiningen: nástroj pro správu projektů napsaných v Clojure (3)
- Leiningen: nástroj pro správu projektů napsaných v Clojure (4)
- Leiningen: nástroj pro správu projektů napsaných v Clojure (5)
- Leiningen: nástroj pro správu projektů napsaných v Clojure (6)
- Programovací jazyk Clojure a databáze (1.část)
- Pluginy pro Leiningen
- Programovací jazyk Clojure a knihovny pro práci s vektory a maticemi
- Programovací jazyk Clojure a knihovny pro práci s vektory a maticemi (2)
- Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk
- Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk (2)
- Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure
- Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure (2)
- Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure (3)
- Programovací jazyk Clojure a práce s Gitem
- Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk (dokončení)
- Programovací jazyk Clojure a práce s Gitem (2)
- Programovací jazyk Clojure – triky při práci s řetězci
- Programovací jazyk Clojure – triky při práci s kolekcemi
- Programovací jazyk Clojure – práce s mapami a množinami
- Programovací jazyk Clojure – základy zpracování XML
- Programovací jazyk Clojure – testování s využitím knihovny Expectations
- Programovací jazyk Clojure – některé užitečné triky použitelné (nejenom) v testech
- Enlive – výkonný šablonovací systém pro jazyk Clojure
- Nástroj Leiningen a programovací jazyk Clojure: tvorba vlastních knihoven pro veřejný repositář Clojars
- Novinky v Clojure verze 1.8.0
- Asynchronní programování v Clojure s využitím knihovny core.async
- Asynchronní programování v Clojure s využitím knihovny core.async (pokračování)
- Asynchronní programování v Clojure s využitím knihovny core.async (dokončení)
- Vytváříme IRC bota v programovacím jazyce Clojure
- Gorilla REPL: interaktivní prostředí pro programovací jazyk Clojure
- Multimetody v Clojure aneb polymorfismus bez použití OOP
- Práce s externími Java archivy v programovacím jazyku Clojure
- Novinky v Clojure verze 1.9.0
- Validace dat s využitím knihovny spec v Clojure 1.9.0
- Použití jazyka Gherkin při tvorbě testovacích scénářů pro aplikace psané v Clojure
- Použití jazyka Gherkin při tvorbě testovacích scénářů pro aplikace psané v Clojure (2)
11. Pixie
„…the first language I ever wrote was when I was in high-school. It was a small interpreted language named PhaLinks and was terrible, but I learned a lot from the effort. I also acquired a distaste for parsers in the process. Which, incidentally, is why I stick with Lisp these days: Lisp parsers are super easy to write.“
Autor programovacího jazyka Pixie.
Další variantou LISPu, s níž jsme se již na stránkách Roota setkali, je jazyk nazvaný Pixie.
Pokud programátoři, kteří propadli kouzlu programovacího jazyka Clojure, potřebují kromě aplikací běžících delší dobu (webový server atd.) vytvářet i kratší skripty spouštěné typicky z příkazové řádky, nezbývá jim nic jiného, než se poohlédnout po alternativních řešeních a jazycích, které se (alespoň prozatím) Clojure pouze podobají a nejsou s ním vždy na 100% kompatibilní. Prozatím pravděpodobně nejpropracovanější variantou je jazyk nazvaný Pixie. Jazyk Pixie využívá just in time překladač (JIT) i správce paměti implementovaný v PyPy (JIT Pythonu psaný v Pythonu), další části Pixie jsou pak psány v jazycích C a C++.
Na rozdíl od Clojure, které se spoléhá na to, že programátoři budou využívat knihovny kompatibilní s vybraným virtuálním strojem (tj. například javovskou standardní knihovnu apod.) se jazyk Pixie spoléhá na rozhraní FFI (Foreign Function Interface) a tím pádem na použití nativních knihoven dostupných v operačním systému, v němž aplikace poběží. Kombinace JITu a GC z PyPy společně s nativními knihovnami se ukazuje být úspěšná, protože skripty psané v Pixie bez výkonnostních problémů fungují i na prvních modelech Raspberry Pi (to se týká i prakticky okamžitého spouštění).
Články s podrobnějšími informacemi o programovacím jazyku Pixie, které již na Rootu vyšly:
- Pixie: lehký skriptovací jazyk s„kouzelnými“ schopnostmi
- Programovací jazyk Pixie: funkce ze základní knihovny a použití FFI
12. Wisp
Zapomenout nesmíme ani na jazyk nazvaný Wisp, o němž jsme se krátce zmínili v předchozí kapitole.
Transpřekladač Wisp slouží k překladu programů vytvořených v programovacím jazyce, který je podmnožinou jazyka Clojure či ClojureScript, do JavaScriptu. Vzhledem k tomu, že i ClojureScript je překládán do JavaScriptu (viz též [1], nabízí se logická otázka, jaký je vlastně mezi ClojureScriptem a Wispem rozdíl.
Cílem autorů ClojureScriptu je nabídnout vývojářům plnohodnotnou alternativní implementaci programovacího jazyka Clojure, což se do značné míry daří, samozřejmě s ohledem na fakt, že současné JavaScriptové enginy nenabízí některé vlastnosti, které Clojure využívá (to například znamená omezené využití agentů či futures). ClojureScript je (trans)překládán do JavaScriptu relativně komplikovaným způsobem; výsledek transpřekladu je dále optimalizován a většinou i „minifikován“, takže se ke klientům dostane již značně nečitelná varianta původního algoritmu (optimalizaci a minifikaci lze při tvorbě zakázat). Díky tomu, že ClojureScript podporuje většinu vlastností jazyka Clojure, je možné při vývoji webových aplikací použít prakticky stejný programovací jazyk jak na straně serveru, tak i na straně klienta, čehož některé společnosti s výhodou využívají.
Transpřekladač Wisp je namísto toho navržen takovým způsobem, aby algoritmus zapsaný v podmnožině jazyka Clojure převedl co nejpřímějším způsobem do JavaScriptu, ideálně tak, aby původní algoritmus byl jasně viditelný i ve vygenerovaném kódu (podle názoru autora může být Wisp z tohoto důvodu takřka ideální učební pomůckou vhodnou pro vysvětlení principu funkcionálních jazyků). Wisp ovšem zachovává některé vlastnosti jazyka Clojure, zejména ty vlastnosti, které jsou odvozeny od LISPu – Wisp je stále homoikonický jazyk (což znamená, že kód je reprezentován stejným způsobem jako data a lze s ním i manipulovat jako s daty), nalezneme zde podporu pro TCO (tail call optimization) a taktéž, což je poměrně důležité, podporu pro makra. Další vlastnosti jazyka Clojure ovšem již podporovány nejsou – protože Wisp používá nativní datové typy JavaScriptu, nenalezneme v něm například skutečné neměnné (immutable) datové struktury, transakční paměť (STM) a i podpora pro líné vyhodnocování (lazy evaluation) je prozatím pouze minimální.
Články s podrobnějšími informacemi o jazyku Wisp:
- Propojení světa LISPu se světem JavaScriptu s využitím transpřekladače Wisp
- Propojení světa LISPu se světem JavaScriptu s využitím transpřekladače Wisp (2.část)
13. Script-fu
Jednou z nejzajímavějších a taktéž nejužitečnějších vlastností grafického editoru GIMP je jeho aplikační programové rozhraní (API) zpřístupňující programátorům prakticky veškerou funkcionalitu GIMPu a taktéž podpora pro skriptování, přičemž skripty mají přímý přístup k API, nezávisle na tom, ve kterém programovacím jazyce byly vytvořeny. Původně se v GIMPu mohly psát skripty pouze v programovacím jazyce Scheme (pro tyto skripty, resp. pro celou technologii, se používá název Script-Fu), ovšem v současnosti existuje i podpora pro populární programovací jazyk Python, který mimochodem některé své vlastnosti převzal právě ze Scheme a LISPu. Skripty používající technologii Script-Fu mohou vytvářet nové obrázky a provádět nad nimi základní grafické operace – kreslení na úrovni jednotlivých pixelů a taktéž kreslení s využitím již existujících kreslicích nástrojů, zejména tužky (pen), štětce (brush) či rozprašovače (airbrush).
Programátor může při tvorbě skriptů určených pro grafický editor GIMP používat širokou paletu objektů spravovaných samotným editorem. Mnohé z těchto objektů jsou dostupné i uživatelům z grafického uživatelského rozhraní editoru, kde je s nimi možné různým způsobem interaktivně manipulovat. Jedná se především o samotné obrázky, dále pak hladiny umisťované do obrázků (kreslení je prováděno do hladin), kanály, tužky, štětce, barvové palety, výběry atd. Skripty psané v programovacím jazyce Python a Scheme mohou buď při svém běhu vytvořit objekty nové, což například může vést ke skutečnému vytvoření nového obrázku, přidání hladiny do obrázku atd., nebo mohou pomocí rozličných dotazovacích funkcí získat některý z již existujících objektů. Například skript, který má vykreslit nějaký objekt do aktivního obrázku, musí získat identifikátor tohoto obrázku (vždy se jedná o celé číslo, protože API GIMPu je poměrně nízkoúrovňové), následně identifikátor hladiny a teprve poté je možné provést požadovanou činnost.
Příklad jednoduchého pluginu pro GIMP:
; Tato funkce je zavolána z dialogu vyvolaného uživatelem ; z grafického uživatelského rozhraní GIMPu. (define (script-draw-circle image-width image-height radius selected-color background-color) (let* ( ; vytvoření nového obrázku, jehož ID se uloží ; do proměnné nazvané "image" (image (car (gimp-image-new image-width image-height RGB))) ; vytvoření nové hladiny, jejíž ID se uloží ; do proměnné nazvané "layer" (layer (car (gimp-layer-new image image-width image-height RGB-IMAGE "Circle" 100 NORMAL-MODE)))) ; přidání hladiny do vytvořeného obrázku (gimp-image-add-layer image layer 0) ; volba barvy v paletě (gimp-palette-set-background background-color) ; vykreslení obrazce - jeho výplň (gimp-edit-fill layer BG-IMAGE-FILL) ; vytvoření výběru ve tvaru kružnice (gimp-image-select-ellipse image ; obrázek v němž se výběr vytvoří CHANNEL-OP-REPLACE ; přepsání oblasti původního výběru (- (/ image-width 2) radius) ; levý horní roh výběru (- (/ image-height 2) radius) (* 2 radius) (* 2 radius)) ; rozměry výběru ; volba barvy v paletě (gimp-palette-set-background selected-color) ; vykreslení obrazce - jeho výplň (gimp-edit-fill layer BG-IMAGE-FILL) ; zrušení výběru (lze vrátit pomocí CTRL+Z) (gimp-selection-none image) ; zobrazení právě vytvořeného obrázku (gimp-display-new image) ; přinutíme GIMP, aby finální obrázek vykreslil (gimp-displays-flush))) ; základní informace o skriptu a definice dialogu ; zobrazeného uživateli (script-fu-register "script-draw-circle" "<Image>/Filters/Render/Pattern/Circle" "Vytvori novy obrazek a v nem nakresli kruznici." "Pavel Tisnovsky" "Pavel Tisnovsky" "2017-05-04" "" SF-ADJUSTMENT "Image width" '(256 16 8192 16 64 0 1) SF-ADJUSTMENT "Image height" '(256 16 8192 16 64 0 1) SF-ADJUSTMENT "Radius" '(50 16 200 16 64 0 1) SF-COLOR "Color" "yellow" SF-COLOR "Background" "black")
Články s podrobnějšími informacemi o jazyku Script-fu:
- Tvorba pluginů pro grafický editor GIMP
- Tvorba pluginů pro grafický editor GIMP (2.část)
- Tvorba pluginů pro grafický editor GIMP (3.část – vykreslení hvězdné oblohy)
- Tvorba pluginů pro grafický editor GIMP 4: použití výběrů (selection) při kreslení a editaci obrázků
14. Hy
Programovací jazyk Hy je ve velké míře inspirován (poměrně populárním) jazykem Clojure, s nímž jsme se na stránkách Roota i v předchozím textu již mnohokrát setkali. Ovšem zatímco interpret Clojure překládá všechny zapsané výrazy do bajtkódu JVM a teprve poté je spouští, pracuje Hy odlišně, protože kód generuje pomocí AST a dokonce dokáže zdrojový LISPovský kód transformovat do Pythonu a teprve poté ho spustit. To je výhodná vlastnost, protože umožňuje projekt Hy integrovat například s debuggery atd. Překlad přes AST do Pythonu podporuje jak Python 2.x, tak i Python 3.x. Další důležitou vlastností Hy představuje možnost plné kooperace mezi kódem zapsaným přímo v tomto jazyku a pythoním kódem, což znamená, že je možné použít všechny Pythonovské knihovny a frameworky (včetně Numpy, PyTorch, Flask atd.) a naopak – například mít napsanou aplikaci v Pythonu a pro manipulaci se symboly použít Hy (v tomto ohledu jsou homoikonické programovací jazyky s makry podle mého názoru mnohem lepší, než samotný Python).
Obrázek 16: Logo programovacího jazyka Hy.
Příklad programu vyvinutého v Hy:
; rekurzivní výpočet faktoriálu (defn factorial [n] (if (<= n 1) 1 (* n (factorial (- n 1))))) (for [n (range 1 11)] (print n (factorial n))) 1 1 2 2 3 6 4 24 5 120 6 720 7 5040 8 40320 9 362880 10 3628800
Články s podrobnějšími informacemi o jazyku Hy:
- Jazyky Hy a Clojure-py: moderní dialekty LISPu určené pro Python VM
- Možnosti nabízené jazykem Hy: moderním dialektem LISPu určeným pro Python VM
15. Clojure-py
Druhým LISPovským programovacím jazykem vytvořeným v Pythonu je jazyk nazvaný Clojure-py. Soudě podle názvu by se mělo jednat o další variantu jazyka Clojure, ovšem projekt Clojure-py je v současnosti v dosti nestabilním stavu, takže například dochází k pádu VM (přesněji řečeno k pádu interpretru) atd. Pro praktické nasazení je mnohem lepší a především méně riskantní použít Hy.
Článek s podrobnějšími informacemi o jazyku Clojure-py:
16. Další programovací jazyky inspirované LISPem
Již v úvodní kapitole jsme si řekli, že jazykem LISP byly do větší či menší míry inspirovány i mnohé další programovací jazyky. Připomeňme si především dva z těchto jazyků, u nichž sice nemusí být inspirace zřejmá na první pohled (zápis programů je mnohdy výrazně odlišný – tj. liší se syntaxe), ovšem sémantika operací jasně ukazuje na to, že tyto jazyky jsou LISPem ovlivněny do velké míry. Jedná se o jazyky Logo a TCL.
17. Jazyk Logo
Programovací jazyk Logo sice z LISPu skutečně vychází, ovšem zatímco většina programovacích jazyků byla vytvořena buď pro praktické programování nebo pro výuku programování, Logo je v tomto smyslu poněkud odlišný jazyk, protože programování zde není cílem ale pouze nástrojem, který má pomoci při vzdělávání. Logo stojí na základech daných takzvanou konstruktivní vzdělávací filozofií a je navrženo k podpoře konstruktivního učení. Konstruktivismus vysvětluje znalosti a dovednosti, jak jsou vytvořeny žáky v jejich vlastních myslích, prostřednictvím vzájemné interakce s jinými lidmi a okolím. Tato zajímavá teorie je spojena především se švýcarským psychologem Jeanem Piagetem, který strávil mnoho času studováním a zdokumentováním učení malých dětí. S Piagetem v Ženevě spolupracoval i Seymour Papert, který později stál u vzniku Loga.
Papert se stal světoznámým díky svému bestselleru Mindstorms, ve kterém popisuje koncepci založenou na tom, že se dětem dá k dispozici jednoduchý ale rozšiřitelný nástroj, přičemž jejich energie a představivost může být použita k nalézání nových možností tohoto nástroje. Oním nástrojem se v této knize (a na mnoha školách a dalších vzdělávacích institucích i v praxi) stalo Logo spolu s jeho želvou. Tím, že dítě „učí“ želvu novým dovednostem, tj. přidává další příkazy do Loga, se samo učí a především formuje svoji osobnost. Tento způsob učení je někdy nazýván „rozhovor se želvou“. Později byl stejný koncept použit například v jazyku Scratch.
Ukažme si ve stručnosti některé jednoduché programy naprogramované v Logu. Nejprve rekurzivní výpočet a vykreslení takzvané dračí křivky, resp. její varianty známé pod jménem C-křivka:
to c_krivka :velikost :uroven if :uroven <= 0 [ forward :velikost stop ] c_krivka :velikost :uroven-1 right 90 c_krivka :velikost :uroven-1 left 90 end
Obrázek 17: Dračí křivka vykreslená předchozí funkcí.
Vykreslení spirály s využitím programové smyčky repeat:
to spiral3 clearscreen hideturtle repeat 3 [ repeat 99 [ right 5 make "d 3*repcount repeat 3 [ forward :d left 120 ] ] ] end (draw 310 310) spiral3
Obrázek 18: Předchozí demonstrační příklad spuštěný v Turtle Tracks
18. Jazyk TCL
I jazyk TCL je inspirován LISPem, což nemusí být na první pohled patrné. Příkladem může být vytvoření proměnné hello, což se v LISPu zapíše takto:
(setq hello "Hello world")
V Tcl se naproti tomu nepoužívají závorky okolo výrazů:
set hello "Hello world"
Vyhodnocování příkazů v jazyce TCL (mimochodem: už samotný pojem vyhodnocování se vztahuje k LISPu) ukazuje, v jaké oblasti TCL získal inspiraci. Při vyhodnocování se totiž provádí takzvané substituce. Substituce se v Tcl používají například k nahrazení jména proměnné její hodnotou – zde se používá znak dolaru. V některých případech by se nám hodilo substituci zakázat. To je samozřejmě možné a děje se tak použitím složených závorek – { a } (což zhruba odpovídá speciální formě quote z LISPu). Rozdíl mezi použitím složených závorek zakazujících substituci a uvozovek umožňujících zápis řetězce s mezerami ukazuje následující příklad. V něm je nejdříve inicializována proměnná answer a tato proměnná je použita při tisku dvou řetězců. V prvním případě se provede substituce jména proměnné na její hodnotu, ve druhém případě se řetězec vytiskne beze změny tak, jak byl zadán:
set answer 42 puts "Odpověď je $answer" puts {Odpověď je $answer}
Složené závorky jsou často použity například při zápisu těla smyček. Je to logické, protože tělo smyčky se nesmí provést již při jejím vytváření, ale až po jejím spuštění. Z tohoto důvodu je nutné prvotní provedení smyčky (která v tomto případě znamená zavolání prvního příkazu v těle smyčky) zakázat:
for { set i 10} {$i < 10} {incr i} { puts "i = : $i" }
Nyní si shrňme všechny prováděné substituce (a jejich opaky) do jedné tabulky:
Použité znaky | Význam znaků |
---|---|
$ | substituce proměnných – náhrada jména proměnné její hodnotou |
[] | vyhodnocení příkazu – příkaz v závorkách se vyhodnotí nejdříve |
"" | potlačuje zpracování mezer jako oddělovačů příkazů či jejich argumentů |
{} | stejné jako uvozovky s tím rozdílem, že se všechny substituce uvnitř závorek zakazují |
\ | ruší zvláštní význam následujícího znaku |
19. Literatura
Knihy o LISPu, Scheme, Clojure a souvisejících tématech:
- 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
- SchemePy
https://pypi.org/project/SchemePy/ - 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/