Jemný úvod do rozsáhlého světa jazyků LISP a Scheme

9. 7. 2019
Doba čtení: 41 minut

Sdílet

 Autor: Conrad Barski, podle licence: Public domain
V právě začínajícím prázdninovém miniseriálu se seznámíme s významnými implementacemi programovacího jazyka LISP, Scheme a i některých odvozených jazyků, mezi něž patří zejména jazyk Clojure a jeho deriváty.

Obsah

1. Jemný úvod do rozsáhlého světa jazyků LISP a Scheme

2. Stručná historie vzniku programovacího jazyka LISP

3. LISP a umělá inteligence

4. Vznik interaktivní smyčky REPL

5. M-výrazy a S-výrazy

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

9. Scheme

10. Clojure

11. Pixie

12. Wisp

13. Script-fu

14. Hy

15. Clojure-py

16. Další programovací jazyky inspirované LISPem

17. Jazyk Logo

18. Jazyk TCL

19. Literatura

20. Odkazy na Internetu

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).

Poznámka: dalším vyšším jazykem vyvinutým již v padesátých letech minulého století, který ve vylepšené podobě „přežil“ až do současnosti, je programovací jazyk FORTRAN neboli plným názvem The IBM Mathematical Formula Translating System. Ten byl vytvořen ve firmě IBM dokonce již v roce 1954 týmem vedeným Johnem W. Backusem (jehož příjmení se mj. objevuje i ve zkratkách BNF a EBNF). Jak již plný význam zkratky FORTRANu napovídá, jedná se o programovací jazyk určený především pro tvorbu aplikací zaměřených na numerické výpočty, podobně jako tomu bylo u vůbec prvního překladače – A-0 vytvořeného již v roce 1952 Grace Hopperovou pro sálový počítač UNIVAC I. Z důvodu zaměření na matematické výpočty byl FORTRAN již od svých prvních verzí (určených původně pouze pro mainframe IBM 704) vybaven všemi základními aritmetickými i relačními operátory, možností práce s komplexními čísly, takzvaným aritmetickým IF (variantou podmíněného příkazu IF, v němž je podmínka vyjádřena aritmetickým výrazem, nikoli výrazem pravdivostním), programovou smyčkou typu DO, možností formátování numerických hodnot při jejich tisku atd.
Poznámka: s mírnou nadsázkou by se dalo říci, že se jednalo o pravý opak LISPu a všechny mainstreamové programovací jazyky byly vytvořeny na škále, jejímiž mezními hodnotami jsou FORTRAN na jedné straně a právě LISP na straně druhé.
ibm-5

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.

lisp01

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.

Poznámka: prefixový zápis operátorů se původně neoficiálně nazýval „Cambridge Polish“ podle takzvané polské (prefixové) notace matematika Jana Łukasiewicze.

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.

Poznámka: REPL si sice většinou spojujeme s interpretovanými programovacími jazyky, ovšem ve skutečnosti je možné smyčku REPL do určité míry používat i u jazyků kompilovaných či překládaných do bajtkódu (příkladem je dále zmíněný programovací jazyk Clojure). Je tomu tak i například v případě jazyka Go, který je kompilovaný a REPL pro něj skutečně vznikl. U jazyka Go je to umožněno zejména díky tomu, že překladač Go je velmi rychlý, takže se v REPL může relativně bez problémů používat překlad každé definice či příkazu, a to i na pomalejších počítačích. Se smyčkou REPL určenou pro jazyk Go jsme se seznámili v článku Užitečné nástroje pro Go: automatické doplňování kódu, plnohodnotná smyčka REPL a integrace s Vimem.
ibm-5

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).

Poznámka: McCarthy skutečně původně chtěl vyjít z FORTRANu, který chtěl jen „nepatrně“ vylepšit. Ovšem již v roce 1957, kdy začal psát rutiny algoritmů pro šachy, si uvědomil, že FORTRAN se svým aritmetickým IF, nemožností volat funkce rekurzivně atd. není pro tento druh práce tím nejvhodnějším nástrojem.

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).

Poznámka: Jazyk Scheme byl používán na MIT v úvodních kurzech programování. V roce 2009 byl nahrazen Pythonem, ovšem Scheme se dále používá, například v kurzu Adventures in Advanced Symbolic Programming (podle některých studentů zdaleka nejzábavnější kurz, kterým prošli).

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).

Poznámka: uvádí se (ovšem bez hlubších měření), že Emacs Lisp je dnes ve světě open source pravděpodobně nejrozšířenější dialog Lispu s největší základnou programů a modulů.
Poznámka 2: pokud sečteme popularitu LISPu, Scheme a Clojure (viz https://www.tiobe.com/tiobe-index/, dojdeme k tomu, že by se společnými silami mohlo dosáhnout první dvacítky (popularita jazyků má ovšem význam spíše při plánování nových projektů a náboru nových programátorů).

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.

hist26

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

hist26

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:

  1. Scheme: kostlivec ve skřini nebo nehasnoucí hvězda?
  2. '(Programovací (cons 'jazyk 'Scheme))
  3. Programovací jazyk Scheme: definice anonymních i pojmenovaných funkcí, iterace
  4. Základy programování v jazyku Scheme
  5. 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:

  1. Clojure 1: Úvod
  2. Clojure 2: Symboly, kolekce atd.
  3. Clojure 3: Funkcionální programování
  4. Clojure 4: Kolekce, sekvence a lazy sekvence
  5. Clojure 5: Sekvence, lazy sekvence a paralelní programy
  6. Clojure 6: Podpora pro paralelní programování
  7. Clojure 7: Další funkce pro paralelní programování
  8. Clojure 8: Identity, stavy, neměnné hodnoty a reference
  9. Clojure 9: Validátory, pozorovatelé a kooperace s Javou
  10. Clojure 10: Kooperace mezi Clojure a Javou
  11. Clojure 11: Generátorová notace seznamu/list comprehension
  12. Clojure 12: Překlad programů z Clojure do bajtkódu JVM I:
  13. Clojure 13: Překlad programů z Clojure do bajtkódu JVM II:
  14. Clojure 14: Základy práce se systémem maker
  15. Clojure 15: Tvorba uživatelských maker
  16. Clojure 16: Složitější uživatelská makra
  17. Clojure 17: Využití standardních maker v praxi
  18. Clojure 18: Základní techniky optimalizace aplikací
  19. Clojure 19: Vývojová prostředí pro Clojure
  20. Clojure 20: Vývojová prostředí pro Clojure (Vimu s REPL)
  21. Clojure 21: ClojureScript aneb překlad Clojure do JS
  22. Leiningen: nástroj pro správu projektů napsaných v Clojure
  23. Leiningen: nástroj pro správu projektů napsaných v Clojure (2)
  24. Leiningen: nástroj pro správu projektů napsaných v Clojure (3)
  25. Leiningen: nástroj pro správu projektů napsaných v Clojure (4)
  26. Leiningen: nástroj pro správu projektů napsaných v Clojure (5)
  27. Leiningen: nástroj pro správu projektů napsaných v Clojure (6)
  28. Programovací jazyk Clojure a databáze (1.část)
  29. Pluginy pro Leiningen
  30. Programovací jazyk Clojure a knihovny pro práci s vektory a maticemi
  31. Programovací jazyk Clojure a knihovny pro práci s vektory a maticemi (2)
  32. Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk
  33. Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk (2)
  34. Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure
  35. Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure (2)
  36. Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure (3)
  37. Programovací jazyk Clojure a práce s Gitem
  38. Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk (dokončení)
  39. Programovací jazyk Clojure a práce s Gitem (2)
  40. Programovací jazyk Clojure – triky při práci s řetězci
  41. Programovací jazyk Clojure – triky při práci s kolekcemi
  42. Programovací jazyk Clojure – práce s mapami a množinami
  43. Programovací jazyk Clojure – základy zpracování XML
  44. Programovací jazyk Clojure – testování s využitím knihovny Expectations
  45. Programovací jazyk Clojure – některé užitečné triky použitelné (nejenom) v testech
  46. Enlive – výkonný šablonovací systém pro jazyk Clojure
  47. Nástroj Leiningen a programovací jazyk Clojure: tvorba vlastních knihoven pro veřejný repositář Clojars
  48. Novinky v Clojure verze 1.8.0
  49. Asynchronní programování v Clojure s využitím knihovny core.async
  50. Asynchronní programování v Clojure s využitím knihovny core.async (pokračování)
  51. Asynchronní programování v Clojure s využitím knihovny core.async (dokončení)
  52. Vytváříme IRC bota v programovacím jazyce Clojure
  53. Gorilla REPL: interaktivní prostředí pro programovací jazyk Clojure
  54. Multimetody v Clojure aneb polymorfismus bez použití OOP
  55. Práce s externími Java archivy v programovacím jazyku Clojure
  56. Novinky v Clojure verze 1.9.0
  57. Validace dat s využitím knihovny spec v Clojure 1.9.0
  58. Použití jazyka Gherkin při tvorbě testovacích scénářů pro aplikace psané v Clojure
  59. 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í).

Poznámka: Pixie není v žádném případě prvním programovacím jazykem, který se do jisté míry snaží napodobit programovací jazyk Clojure. Mj. jsme se již setkali s programovacím jazykem Wisp, který je automaticky s využitím takzvaného transpileru transformován do JavaScriptu, dále existuje sémanticky podobný jazyk naprogramovaný v Perlu atd. Ovšem Pixie je z těchto jazyků nejpropracovanější a především pak prakticky využitelný.

Články s podrobnějšími informacemi o programovacím jazyku Pixie, které již na Rootu vyšly:

  1. Pixie: lehký skriptovací jazyk s„kouzelnými“ schopnostmi
  2. 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:

  1. Propojení světa LISPu se světem JavaScriptu s využitím transpřekladače Wisp
  2. 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).

Poznámka: ve skutečnosti je možné přes PDB (Procedural Database) ovládat GIMP i z dalších jazyků, například z Perlu. Ovšem Scheme a Python jsou zdaleka nejpoužívanější.

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:

  1. Tvorba pluginů pro grafický editor GIMP
  2. Tvorba pluginů pro grafický editor GIMP (2.část)
  3. Tvorba pluginů pro grafický editor GIMP (3.část – vykreslení hvězdné oblohy)
  4. 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).

hist26

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:

  1. Jazyky Hy a Clojure-py: moderní dialekty LISPu určené pro Python VM
  2. 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:

  1. Jazyky Hy a Clojure-py: moderní dialekty LISPu určené pro Python VM

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
logo0803

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
logo1201

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:

bitcoin_skoleni

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
Poznámka: na tomto místě je vhodné upozornit na to, že LISP automaticky vyhodnocuje všechny výrazy (tj. provádí substituci výrazu za jeho výsledek), pokud ovšem nejsou uzavřeny ve speciální formě quote, kterou lze většinou zapsat i zkráceně pomocí apostrofu. Žádné další podmínky pro substituci/nesubstituci není nutné specifikovat. V jazyku TCL se jeho autor rozhodl pro opačný přístup: ve výchozím stavu se substituce neprovádí, což možná může znít logicky, ovšem jak je vidět z předchozí tabulky, bylo ve skutečnosti nutné do jazyka přidat další podmínky kdy a za jakých okolností se substituce může provést. Z tohoto pohledu je návrh LISPu mnohem čistší (není se ostatně čemu divit, protože vychází z minimalistického lambda kalkulu).

19. Literatura

Knihy o LISPu, Scheme, Clojure a souvisejících tématech:

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

20. Odkazy na Internetu

  1. SchemePy
    https://pypi.org/project/SchemePy/
  2. lispy
    https://pypi.org/project/lispy/
  3. Lython
    https://pypi.org/project/Lython/
  4. Lizpop
    https://pypi.org/project/lizpop/
  5. Budoucnost programovacích jazyků
    http://www.knesl.com/budoucnost-programovacich-jazyku
  6. LISP Prolog and Evolution
    http://blog.samibadawi.com/2013/05/lisp-prolog-and-evolution.html
  7. List of Lisp-family programming languages
    https://en.wikipedia.org/wi­ki/List_of_Lisp-family_programming_languages
  8. clojure_py na indexu PyPi
    https://pypi.python.org/py­pi/clojure_py
  9. PyClojure
    https://github.com/eigenhom­bre/PyClojure
  10. Hy na GitHubu
    https://github.com/hylang/hy
  11. Hy: The survival guide
    https://notes.pault.ag/hy-survival-guide/
  12. Hy běžící na monitoru terminálu společnosti Symbolics
    http://try-hy.appspot.com/
  13. Welcome to Hy’s documentation!
    http://docs.hylang.org/en/stable/
  14. Hy na PyPi
    https://pypi.org/project/hy/#des­cription
  15. Getting Hy on Python
    https://lwn.net/Articles/596626/
  16. Programming Can Be Fun with Hy
    https://opensourceforu.com/2014/02/pro­gramming-can-fun-hy/
  17. Přednáška o projektu Hy (pětiminutový lighttalk)
    http://blog.pault.ag/day/2013/04/02
  18. Hy (Wikipedia)
    https://en.wikipedia.org/wiki/Hy
  19. GNU Emacs Lisp Reference Manual: Point
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Point.html
  20. GNU Emacs Lisp Reference Manual: Narrowing
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Narrowing.html
  21. GNU Emacs Lisp Reference Manual: Functions that Create Markers
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Creating-Markers.html
  22. GNU Emacs Lisp Reference Manual: Motion
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Motion.html#Motion
  23. GNU Emacs Lisp Reference Manual: Basic Char Syntax
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Basic-Char-Syntax.html
  24. Elisp: Sequence: List, Array
    http://ergoemacs.org/emac­s/elisp_list_vs_vector.html
  25. Elisp: Property List
    http://ergoemacs.org/emac­s/elisp_property_list.html
  26. Elisp: Hash Table
    http://ergoemacs.org/emac­s/elisp_hash_table.html
  27. Elisp: Association List
    http://ergoemacs.org/emac­s/elisp_association_list.html
  28. The mapcar Function (An Introduction to Programming in Emacs Lisp)
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­intr/mapcar.html
  29. Anaphoric macro
    https://en.wikipedia.org/wi­ki/Anaphoric_macro
  30. Some Common Lisp Loop Macro Examples
    https://www.youtube.com/wat­ch?v=3yl8o6r_omw
  31. A Guided Tour of Emacs
    https://www.gnu.org/softwa­re/emacs/tour/
  32. The Roots of Lisp
    http://www.paulgraham.com/ro­otsoflisp.html
  33. Evil (Emacs Wiki)
    https://www.emacswiki.org/emacs/Evil
  34. Evil (na GitHubu)
    https://github.com/emacs-evil/evil
  35. Evil (na stránkách repositáře MELPA)
    https://melpa.org/#/evil
  36. Evil Mode: How I Switched From VIM to Emacs
    https://blog.jakuba.net/2014/06/23/e­vil-mode-how-to-switch-from-vim-to-emacs.html
  37. GNU Emacs (home page)
    https://www.gnu.org/software/emacs/
  38. GNU Emacs (texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?GnuEmacs
  39. An Introduction To Using GDB Under Emacs
    http://tedlab.mit.edu/~dr/gdbin­tro.html
  40. An Introduction to Programming in Emacs Lisp
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­intr/index.html
  41. 27.6 Running Debuggers Under Emacs
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­macs/Debuggers.html
  42. GdbMode
    http://www.emacswiki.org/e­macs/GdbMode
  43. Emacs (Wikipedia)
    https://en.wikipedia.org/wiki/Emacs
  44. Emacs timeline
    http://www.jwz.org/doc/emacs-timeline.html
  45. Emacs Text Editors Family
    http://texteditors.org/cgi-bin/wiki.pl?EmacsFamily
  46. Vrapper aneb spojení možností Vimu a Eclipse
    https://mojefedora.cz/vrapper-aneb-spojeni-moznosti-vimu-a-eclipse/
  47. 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/
  48. Emacs/Evil-mode – A basic reference to using evil mode in Emacs
    http://www.aakarshnair.com/posts/emacs-evil-mode-cheatsheet
  49. From Vim to Emacs+Evil chaotic migration guide
    https://juanjoalvarez.net/es/de­tail/2014/sep/19/vim-emacsevil-chaotic-migration-guide/
  50. Introduction to evil-mode {video)
    https://www.youtube.com/wat­ch?v=PeVQwYUxYEg
  51. EINE (Emacs Wiki)
    http://www.emacswiki.org/emacs/EINE
  52. EINE (Texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?EINE
  53. ZWEI (Emacs Wiki)
    http://www.emacswiki.org/emacs/ZWEI
  54. ZWEI (Texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?ZWEI
  55. Zmacs (Wikipedia)
    https://en.wikipedia.org/wiki/Zmacs
  56. Zmacs (Texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?Zmacs
  57. TecoEmacs (Emacs Wiki)
    http://www.emacswiki.org/e­macs/TecoEmacs
  58. Micro Emacs
    http://www.emacswiki.org/e­macs/MicroEmacs
  59. Micro Emacs (Wikipedia)
    https://en.wikipedia.org/wi­ki/MicroEMACS
  60. EmacsHistory
    http://www.emacswiki.org/e­macs/EmacsHistory
  61. Seznam editorů s ovládáním podobným Emacsu či kompatibilních s příkazy Emacsu
    http://www.finseth.com/emacs.html
  62. evil-numbers
    https://github.com/cofi/evil-numbers
  63. Debuggery a jejich nadstavby v Linuxu (1.část)
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu/
  64. Debuggery a jejich nadstavby v Linuxu (2.část)
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-2-cast/
  65. Debuggery a jejich nadstavby v Linuxu (3): Nemiver
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-3-nemiver/
  66. Debuggery a jejich nadstavby v Linuxu (4): KDbg
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-4-kdbg/
  67. 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/
  68. Org mode
    https://orgmode.org/
  69. The Org Manual
    https://orgmode.org/manual/index.html
  70. Kakoune (modální textový editor)
    http://kakoune.org/
  71. Vim-style keybinding in Emacs/Evil-mode
    https://gist.github.com/tro­yp/6b4c9e1c8670200c04c16036805773d8
  72. Emacs – jak začít
    http://www.abclinuxu.cz/clan­ky/navody/emacs-jak-zacit
  73. Programovací jazyk LISP a LISP machines
    https://www.root.cz/clanky/pro­gramovaci-jazyk-lisp-a-lisp-machines/
  74. Evil-surround
    https://github.com/emacs-evil/evil-surround
  75. Spacemacs
    http://spacemacs.org/
  76. Lisp: Common Lisp, Racket, Clojure, Emacs Lisp
    http://hyperpolyglot.org/lisp
  77. Common Lisp, Scheme, Clojure, And Elisp Compared
    http://irreal.org/blog/?p=725
  78. Does Elisp Suck?
    http://irreal.org/blog/?p=675
  79. Emacs pro mírně pokročilé (9): Elisp
    https://www.root.cz/clanky/emacs-elisp/
  80. If I want to learn lisp, are emacs and elisp a good choice?
    https://www.reddit.com/r/e­macs/comments/2m141y/if_i_wan­t_to_learn_lisp_are_emacs_an­d_elisp_a/
  81. Clojure(Script) Interactive Development Environment that Rocks!
    https://github.com/clojure-emacs/cider
  82. An Introduction to Emacs Lisp
    https://harryrschwartz.com/2014/04/08/an-introduction-to-emacs-lisp.html
  83. Emergency Elisp
    http://steve-yegge.blogspot.com/2008/01/emergency-elisp.html
  84. Lambda calculus
    https://en.wikipedia.org/wi­ki/Lambda_calculus
  85. John McCarthy's original LISP paper from 1959
    https://www.reddit.com/r/pro­gramming/comments/17lpz4/joh­n_mccarthys_original_lisp_pa­per_from_1959/
  86. Micro Manual LISP
    https://www.scribd.com/do­cument/54050141/Micro-Manual-LISP
  87. How Lisp Became God's Own Programming Language
    https://twobithistory.org/2018/10/14/lis­p.html
  88. History of Lisp
    http://jmc.stanford.edu/ar­ticles/lisp/lisp.pdf
  89. The Roots of Lisp
    http://languagelog.ldc.upen­n.edu/myl/llog/jmc.pdf
  90. Racket
    https://racket-lang.org/
  91. The Racket Manifesto
    http://felleisen.org/matthi­as/manifesto/
  92. MIT replaces Scheme with Python
    https://www.johndcook.com/blog/2009/03/26/mit-replaces-scheme-with-python/
  93. Adventures in Advanced Symbolic Programming
    http://groups.csail.mit.e­du/mac/users/gjs/6.945/
  94. Why MIT Switched from Scheme to Python (2009)
    https://news.ycombinator.com/i­tem?id=14167453
  95. Starodávná stránka XLispu
    http://www.xlisp.org/
  96. AutoLISP
    https://en.wikipedia.org/wi­ki/AutoLISP
  97. Seriál PicoLisp: minimalistický a výkonný interpret Lispu
    https://www.root.cz/serialy/picolisp-minimalisticky-a-vykonny-interpret-lispu/
  98. Common Lisp
    https://common-lisp.net/
  99. Getting Going with Common Lisp
    https://cliki.net/Getting%20Started
  100. Online Tutorial (Common Lisp)
    https://cliki.net/online%20tutorial
  101. Guile Emacs
    https://www.emacswiki.org/e­macs/GuileEmacs
  102. Guile Emacs History
    https://www.emacswiki.org/e­macs/GuileEmacsHistory
  103. Guile is a programming language
    https://www.gnu.org/software/guile/
  104. MIT Scheme
    http://groups.csail.mit.e­du/mac/projects/scheme/
  105. SIOD: Scheme in One Defun
    http://people.delphiforum­s.com/gjc//siod.html
  106. CommonLispForEmacs
    https://www.emacswiki.org/e­macs/CommonLispForEmacs
  107. Elisp: print, princ, prin1, format, message
    http://ergoemacs.org/emac­s/elisp_printing.html
  108. Special Forms in Lisp
    http://www.nhplace.com/ken­t/Papers/Special-Forms.html
  109. Basic Building Blocks in LISP
    https://www.tutorialspoin­t.com/lisp/lisp_basic_syn­tax.htm
  110. Introduction to LISP – University of Pittsburgh
    https://people.cs.pitt.edu/~mi­los/courses/cs2740/Lectures/Lis­pTutorial.pdf
  111. Why don't people use LISP
    https://forums.freebsd.org/threads/why-dont-people-use-lisp.24572/
  112. Structured program theorem
    https://en.wikipedia.org/wi­ki/Structured_program_the­orem
  113. Clojure: API Documentation
    https://clojure.org/api/api
  114. Tutorial for the Common Lisp Loop Macro
    http://www.ai.sri.com/pkarp/loop.html
  115. Common Lisp's Loop Macro Examples for Beginners
    http://www.unixuser.org/~e­uske/doc/cl/loop.html
  116. A modern list api for Emacs. No 'cl required.
    https://github.com/magnars/dash.el
  117. The LOOP Facility
    http://www.lispworks.com/do­cumentation/HyperSpec/Body/06_a­.htm
  118. Clojure.org: Vars and the Global Environment
    http://clojure.org/Vars
  119. Clojure.org: Refs and Transactions
    http://clojure.org/Refs
  120. Clojure.org: Atoms
    http://clojure.org/Atoms
  121. Clojure.org: Agents as Asynchronous Actions
    http://clojure.org/agents
  122. Transient Data Structureshttp://clojure.or­g/transients
  123. Dynamic Languages Strike Back
    http://steve-yegge.blogspot.cz/2008/05/dynamic-languages-strike-back.html
  124. Scripting: Higher Level Programming for the 21st Century
    http://www.tcl.tk/doc/scripting.html
  125. Clojure (na Wikipedia EN)
    http://en.wikipedia.org/wiki/Clojure
  126. Clojure (na Wikipedia CS)
    http://cs.wikipedia.org/wiki/Clojure
  127. SICP (The Structure and Interpretation of Computer Programs)
    http://mitpress.mit.edu/sicp/
  128. Pure function
    http://en.wikipedia.org/wi­ki/Pure_function
  129. Funkcionální programování
    http://cs.wikipedia.org/wi­ki/Funkcionální_programová­ní
  130. 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/
  131. Pixie: lehký skriptovací jazyk s „kouzelnými“ schopnostmi
    https://www.root.cz/clanky/pixie-lehky-skriptovaci-jazyk-s-kouzelnymi-schopnostmi/
  132. Programovací jazyk Pixie: funkce ze základní knihovny a použití FFI
    https://www.root.cz/clanky/pro­gramovaci-jazyk-pixie-funkce-ze-zakladni-knihovny-a-pouziti-ffi/

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.