Basilisp: interpret programovacího jazyka Clojure integrovaný s Pythonem

13. 11. 2025
Doba čtení: 66 minut

Sdílet

Komiksový obrázek baziliška
Autor: Root.cz s využitím Zoner AI
Koncept jazyka LISP vznikl již před 65 roky. Od té doby bylo vytvořeno možná i několik tisíc implementací. Dnes se seznámíme s Basilispem. Jde o interpret jazyka Clojure, jenž je integrovaný s platformou Pythonu.

Obsah

1. Basilisp: interpret programovacího jazyka Clojure integrovaný s Pythonem

2. Python VM ve funkci platformy pro další programovací jazyky

3. Projekt Basilisp

4. Instalace projektu Basilisp

5. První kroky v interaktivní smyčce jazyka Basilisp

6. Literály a jednoduché formy, s nimiž se v Basilispu pracuje

7. Symboly a hesla

8. Složené formy: strukturované datové typy

9. Příklady konstrukce kolekcí v programovacím jazyku Basilisp

10. Operace s kolekcemi a nekonečnými sekvencemi

11. Predikáty, zjištění typových informací za běhu

12. Řídicí struktury (speciální formy a makra)

13. Ukázky využití vybraných řídicích struktur

14. Konstrukce cond a condp

15. Balíčky dodávané se samotným jazykem Basilisp

16. Interoperabilita s Pythonem

17. Využití balíčků Pythonu přímo z Basilispu

18. Předchozí části seriálu o LISPovských programovacích jazycích

19. Literatura

20. Odkazy na Internetu

1. Basilisp: interpret programovacího jazyka Clojure integrovaný s Pythonem

Svět programovacího jazyka LISP je velmi rozsáhlý a dá se říci, že i pestrý. Jak již bylo napsáno v perexu dnešního článku, vznikl koncept tohoto programovacího jazyka již před neuvěřitelnými 65 roky a od té doby bylo vytvořeno několik set, ale s poměrně velkou pravděpodobností i několik tisíc implementací LISPu popř. od něj odvozených jazyků Scheme a Clojure. LISPy tak najdeme jak na osmibitových domácích mikropočítačích na jedné straně, tak i na superpočítačích na straně druhé. V dnešním článku se seznámíme s projektem nazvaným Basilisp. Jedná se o interpret programovacího jazyka Clojure, který je integrovaný s platformou Pythonu (naproti tomu klasický Clojure je integrovaný s JVM a ClojureScript s JavaScriptem). Velkou předností Basilispu je téměř dokonalé navázání na Python a jeho knihovny – dokonce je integrace lepší, než Clojure+Java, protože Basilisp má s Pythonem podobný typový systém.

Spojení dialektu LISPu s virtuálním strojem Pythonu popř. přímo s programovacím jazykem Python (tzv. interop) není zajímavé jen z technologického hlediska, protože může mít i praktické využití. Ostatně LISP byl jazykem používaným pro vývoj systémů umělé inteligence, a to už v padesátých letech minulého století (z dnešního pohledu se ale mnohdy jednalo spíš o hledání slepých uliček). A dnes má v oblasti AI a strojového učení stejně výsadní postavení Python, takže se vlastně spojení LISP+Python jeví jako poměrně pragmatická volba.

Poznámka: z hlediska statistiky GitHubu se již jedná o stabilnější typ projektu s deseti přispěvateli a relativně dlouhou historií vylepšení (viz též příslušný repositář). Na druhou stranu však nemůže soupeřit například se statistikou samotného Clojure nebo dokonce Pythonu.

2. Python VM ve funkci platformy pro další programovací jazyky

Fakt, že různé dialekty jazyků LISP a Scheme (popř. Clojure, který lze považovat za moderní reinkarnaci LISPu) vznikají pro prakticky všechny moderní virtuální stroje (typicky pro JVM, VM JavaScriptu, WASM nebo VM Pythonu) vlastně není nic překvapivého. Musíme si totiž uvědomit, že praktická použitelnost programovacího jazyka je do značné míry určena i celým ekosystémem, který je programátorům, kteří chtějí tento jazyk začít používat, k dispozici. A ekosystém Pythonu je dnes již velmi rozsáhlý a obsahuje kvalitní a v celém světě používané knihovny i celé frameworky, takže se může jednat o vhodný základ, na němž je možné postavit moderní varianty LISPu.

Na podobné myšlence ostatně vznikl i výše zmíněný jazyk Clojure, který vlastně vůbec nemá svůj vlastní virtuální stroj. Clojure vzniklo pro virtuální stroj Javy (JVM – Java Virtual Machine), další varianty Clojure byly implementovány pro CLR (ClojureCLR) a ClojureScript, který je kompilovaný do JavaScriptu, takže může běžet buď v prohlížeči, v Node.js atd. V každém případě však Clojure dokáže využít všechny dostupné knihovny pro zvolenou platformu.

Pro virtuální stroj jazyka Python (Python VM) je v současnosti k dispozici hned několik dialektů LISPu, Scheme či Clojure. Jedná se například o méně známé projekty Lizpop, Lispy či Lython, dále o SchemePy, Clojure-py a taktéž velmi zajímavým způsobem implementovaný programovací jazyk nazvaný Hy. Do této kategorie částečně spadá i programovací jazyk Pixie, se kterým jsme se již na stránkách Roota seznámili. A dalším členem této již tak rozsáhlé rodiny je projekt Basilisp, kterému se budeme primárně věnovat v dnešním článku.

3. Projekt Basilisp

Projekt Basilisp je implementací programovacího jazyka Clojure (resp. přesněji řečeno velké části tohoto jazyka) pro platformu klasického CPythonu. Ovšem to, že Basilisp běží nad virtuálním strojem Pythonu není pouhý implementační detail, ale důležitá vlastnost, protože Basilisp dokáže prakticky bezproblémově volat funkce a metody samotného Pythonu, dokáže importovat Pythonní balíčky atd. Rozhraní mezi Pythonem a Basilispem samozřejmě není zcela bezproblémové, protože se zde střetává svět Pythonu s (obecně) měnitelnými datovými strukturami na straně jedné a svět neměnitelných a persistentních datových struktur na straně druhé. Ovšem, ostatně jak uvidíme v navazujících kapitolách, je možné i tento problém řešit celkem elegantním způsobem. Basilisp samotný obsahuje podporu pro interaktivní smyčku REPL, která se navíc inicializuje rychleji, než je tomu v klasickém Clojure postaveném nad virtuálním strojem Javy.

Poznámka: zajímavé je, že se v projektu Basilisp používají balíčky s implementací persistentních datových struktur. Touto problematikou jsme se již na stránkách Roota zabývali ve dvojici článků Pyrsistent: persistentní datové struktury v Pythonu a Pyrsistent: persistentní datové struktury v Pythonu (dokončení).

4. Instalace projektu Basilisp

Basilisp je dostupný ve formě běžného Pythonního balíčku, takže je možné pro jeho instalaci použít například nástroj pip. Ovšem pro první pokusy s tímto projektem bude lepší instalace do samostatného adresáře, resp. přesněji řečeno do virtuálního prostředí Pythonu. Pro tuto variantu instalaci použiji nástroj uv, i když naprosto stejným způsobem lze využít pdm atd.

Nejprve si necháme vygenerovat adresář se základní kostrou Pythonního projektu:

$ uv init basilisp-project
 
Initialized project `basilisp-project` at `/tmp/ramdisk/basilisp-project`

Měl by vzniknout nový adresář s následujícím obsahem:

drwxr-xr-x. 3 ptisnovs ptisnovs 160 Nov  8 10:32 .
drwxr-xr-x. 3 ptisnovs ptisnovs  60 Nov  8 10:32 ..
drwxr-xr-x. 6 ptisnovs ptisnovs 180 Nov  8 10:32 .git
-rw-r--r--. 1 ptisnovs ptisnovs 109 Nov  8 10:32 .gitignore
-rw-r--r--. 1 ptisnovs ptisnovs  94 Nov  8 10:32 main.py
-rw-r--r--. 1 ptisnovs ptisnovs 162 Nov  8 10:32 pyproject.toml
-rw-r--r--. 1 ptisnovs ptisnovs   5 Nov  8 10:32 .python-version
-rw-r--r--. 1 ptisnovs ptisnovs   0 Nov  8 10:32 README.md

Přesuneme se do nově vytvořeného adresáře a nainstalujeme Basilisp do virtuálního prostředí:

$ cd basilisp-project
 
$ uv add basilisp
 
Using CPython 3.12.10 interpreter at: /usr/bin/python3.12
Creating virtual environment at: .venv
Resolved 8 packages in 481ms
Prepared 3 packages in 236ms
Installed 7 packages in 12ms
 + attrs==25.4.0
 + basilisp==0.4.0
 + immutables==0.21
 + prompt-toolkit==3.0.52
 + pyrsistent==0.20.0
 + typing-extensions==4.15.0
 + wcwidth==0.2.14
Poznámka: povšimněte si, že se mj. nainstalovala i knihovna immutables a pyrsistent.

Současně by měly být zaregistrovány nové příkazy/nástroje spustitelné přes uv run:

$ uv run
 
Provide a command or script to invoke with `uv run <;command>` or `uv run <script>.py`.
 
The following commands are available in the environment:
 
- basilisp
- basilisp-run
- python
- python3
- python3.12

My budeme v praktické části článku spouštět příkaz/nástroj basilisp, který má sám další volby:

$ uv run basilisp
 
usage: basilisp [-h] {bootstrap,nrepl-server,repl,run,test,version} ...
 
Basilisp is a Lisp dialect inspired by Clojure targeting Python 3.
 
positional arguments:
  {bootstrap,nrepl-server,repl,run,test,version}
                        sub-commands
    bootstrap           bootstrap the Python installation to allow importing Basilisp namespaces
    nrepl-server        start the nREPL server
    repl                start the Basilisp REPL
    run                 run a Basilisp script or code or namespace
    test                run tests in a Basilisp project
    version             print the version of Basilisp
 
options:
  -h, --help            show this help message and exit

5. První kroky v interaktivní smyčce jazyka Basilisp

Basilisp je vybaven plnohodnotnou interaktivní smyčkou REPL (Read Eval Print Loop), která nabízí možnost editace příkazového řádku, práci s historií příkazů, obsahuje jednoduchou nápovědu (postačuje napsat část příkazu a nabídne se jeho doplnění), zvýraznění syntaxe a především pak „doskoky“ na párové závorky, což je pro LISPovský programovací jazyk velmi důležité.

REPL se spustí následovně:

$ uv run basilisp repl
 
basilisp.user=>
Poznámka: zobrazená výzva (prompt) před šipkou ⇒ zobrazuje takzvaný jmenný prostor (namespace).

Zadané výrazy jsou ihned vyhodnocovány. Například forma * (makro nebo funkce) pro součin hodnot se ihned po potvrzení klávesou Enter vyhodnotí a výsledek se vypíše:

basilisp.user=> (* 6 7)
 
42

Ke každému načtenému symbolu je možné zobrazit nápovědu pomocí doc:

basilisp.user=> (doc +)
 
------------------------
basilisp.core/+
([] [x] [x y] [x y & args])
  Sum the arguments together. If no arguments given, returns 0.
nil

Nápověda k samotné funkci zobrazující nápovědu:

basilisp.user=> (doc doc)
 
------------------------
basilisp.repl/doc
([&env &form v])
  Print the docstring from an interned Var if found.

  ``v`` must be a symbol which resolves to a Var.
nil

Nápověda k velmi užitečné konstrukci range:

basilisp.user=> (doc range)
 
------------------------
basilisp.core/range
([] [end] [start end] [start end step])
  Return a range of integers from ``start``\. If ``end`` is specified, the sequence
  will terminate at ``end``\. If ``step`` is specified, that amount will be added
  for each iteration. ``step`` may be negative.
nil
Poznámka: nil na konci všech předchozích výrazů je výsledek volání doc.

Zajímavé a užitečné je, že vývojář má přímý přístup k základním funkcím Pythonu. Ty se volají naprosto stejně, jakoby se jednalo o samotné funkce Basilispu:

basilisp.user=> (hex 42)
 
"0x2a"
basilisp.user=> (abs -42)
 
42

Ovšem zavolat můžeme například i vestavěnou funkci help (ta je interaktivní):

basilisp.user=> (help)
 
Welcome to Python 3.12's help utility! If this is your first time using
Python, you should definitely check out the tutorial at
https://docs.python.org/3.12/tutorial/.
 
Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules.  To get a list of available
modules, keywords, symbols, or topics, enter "modules", "keywords",
"symbols", or "topics".
 
Each module also comes with a one-line summary of what it does; to list
the modules whose name or summary contain a given string such as "spam",
enter "modules spam".
 
To quit this help utility and return to the interpreter,
enter "q" or "quit".
 
help>

Příklad spuštění a vyhodnocení range (podrobnosti budou uvedeny později):

basilisp.user=> (range 10)
 
(0 1 2 3 4 5 6 7 8 9)

Nápověda k další velmi užitečné funkci (vyššího řádu) nazvané reduce:

basilisp.user=> (doc reduce)
 
------------------------
basilisp.core/reduce
([f coll] [f val coll])
  Reduce ``coll`` by ``f``\.
 
  If ``val`` is not supplied and ``coll`` has no elements, ``f`` will be called with no
  arguments and the result will be returned.
 
  If ``val`` is not supplied and ``coll`` has one element, the result of
  ``(f (first val))`` is returned.
 
  If ``val`` is not supplied and ``coll`` has elements, repeatedly reduce ``coll`` by
  calling ``f`` on successive elements in ``coll``\.
 
  If ``val`` is supplied and ``coll`` has no elements, return ``val` and ``f`` will not
  be called.
 
  If ``val`` is supplied and ``coll`` has elements, repeatedly reduce ``coll`` by
  calling ``f`` on successive elements in ``coll``\, starting with ``val``\.
 
  If ``f`` returns a ``reduced`` value at any point, reduction will terminate and the
  reduced value will be returned immediately.

Využití funkce reduce pro výpočet faktoriálu 1000 (podrobnosti opět budou uvedeny později):

basilisp.user=> (reduce * (range 1 1000))
 
40238726007709377354370243392300398571937486421071463254379991042993851239862902
05920442084869694048004799886101971960586316668729948085589013238296699445909974
24504087073759918823627727188732519779505950995276120874975462497043601418278094
64649629105639388743788648733711918104582578364784997701247663288983595573543251
31853239584630755574091142624174743493475534286465766116677973966688202912073791
43853719588249808126867838374559731746136085379534524221586593201928090878297308
43139284440328123155861103697680135730421616874760967587134831202547858932076716
91324484262361314125087802080002616831510273418279777047846358681701643650241536
91398281264810213092761244896359928705114964975419909342221566832572080821333186
11681155361583654698404670897560290095053761647584772842188967964624494516076535
34081989013854424879849599533191017233555566021394503997362807501378376153071277
61926849034352625200015888535147331611702103968175921510907788019393178114194545
25722386554146106289218796022383897147608850627686296714667469756291123408243920
81601537808898939645182632436716167621791689097799119037540312746222899880051954
44414282012187361745992642956581746628302955570299024324153181617210465832036786
90611726015878352075151628422554026517048330422614397428693306169089796848259012
54583271682264580665267699586526822728070757813918581788896522081643483448259932
66043367660176999612831860788386150279465955131156552036093988180612138558600301
43569452722420634463179746059468257310379008402443243846565724501440282188525247
09351906209290231364932734975655139587205596542287497740114133469627154228458623
77387538230483865688976461927383814900140767310446640259899490222221765904339901
88601856652648506179970235619389701786004081188972991831102117122984590164192106
88843871218556461249607987229085192968193723886426148396573822911231250241866493
53143970137428531926649875337218940694281434118520158014123344828015051399694290
15348307764456909907315243327828826986460278986432113908350621709500259738986355
42771967428222487575867657523442202075736305694988250879689281627538488633969099
59826280956121450994871701244516461260379029309120889086942028510640182154399457
15680594187274899809425474217358240106367740459574178516082923013535808184009699
63725242305608559037006242712434169090041536901059339838357779394109700277534720
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000

6. Literály a jednoduché formy, s nimiž se v Basilispu pracuje

Nyní se již (konečně!) můžeme seznámit se základními stavebními prvky, na kterých je programovací jazyk Basilisp postaven. Všechny příklady, které zde budou ukázány, jsou spouštěny interaktivně ze smyčky REPL, což znamená, že každý výraz je nejprve načten (read), vyhodnocen (evaluate), posléze je jeho výsledek vypsán na standardní výstup (print) a následně je očekáváno interaktivní zadání dalšího výrazu (loop). Všechny dále uvedené výrazy jsou jednořádkové, takže na prvním řádku je vypsán vlastní výraz (tak jak má být opsán do konzole) a na řádku druhém výsledek tohoto výrazu.

V předchozích větách jsme sice pro jednoduchost používali slovo „výraz“ odpovídající spíše jazykům typu Céčka či Javy, ovšem v případě Basilispu je, podobně jako v jiných variantách LISPu či Scheme, základním uceleným prvkem programu takzvaná forma (form). Právě formy se postupně zpracovávají v interaktivní smyčce REPL a REPL taktéž kontroluje, zda uživatel skutečně zadal validní formu. V programovacím jazyku Basilisp (ale i v Clojure) existují čtyři základní typy forem:

  1. literály
  2. symboly a hesla (keywords)
  3. složené formy (v podstatě se jedná o seznamy představující volání funkce)
  4. speciální formy (podobají se složeným formám, ale interně se vyhodnocují odlišným způsobem, například se rekurzivně nevyhodnocují vnitřní podvýrazy atd.)

Nejjednodušším typem formy jsou literály, protože ty se v interaktivní smyčce REPL vyhodnocují samy na sebe. Na literály se můžeme dívat jako na konstanty nějakého primitivního datového typu, mezi které v programovacím jazyce Basilisp patří především čísla (k dispozici jsou různé formy reprezentace), znaky, řetězce a pravdivostní hodnoty. Nyní si ukážeme několik příkladů, které naznačí, jak s literály pracuje REPL a tudíž i samotný programovací jazyk Basilisp.

Řetězec je prostě … řetězec. Zapisuje se do dvojitých uvozovek (apostrofy a zpětné apostrofy mají odlišný význam):

basilisp.user=> "Hello"
Hello

Důležité je, že řetězce jsou – podobně jako v Pythonu nebo i v Javě – konstantní a tudíž i neměnné (immutable), což sice v některých případech může vést k tvorbě neefektivních operací, kterým se však lze v Basilispu většinou zcela vyhnout. To, že jsou řetězce neměnné však zjednodušuje tvorbu bezpečných vícevláknových aplikací, řetězce lze využívat jako klíče do asociativních polí atd. atd., takže přednosti většinou převažují nad zápory.

Pozor je nutné dát na to, že některé další typy Pythonovských řetězců nejsou podporovány. Například nelze uvést prefix u:

basilisp.user=> u"Hello"
 
  exception: <class 'basilisp.lang.compiler.exception.CompilerException'>
      phase: :analyzing
    message: unable to resolve symbol 'u' in this context
       form: u
   location: <REPL Input>:1

Podporovány nejsou ani formátovací řetězce (a už vůbec ne řetězce konvertované na šablonu, což je novinka Pythonu 3.14):

basilisp.user=> f"Hello"
 
  exception: <class 'basilisp.lang.compiler.exception.CompilerException'>
      phase: :analyzing
    message: unable to resolve symbol 'f' in this context
       form: f
   location: <REPL Input>:1
basilisp.user=> """Hello"""
 
""

Použití literálů představujících pravdivostní hodnoty asi nikoho nepřekvapí:

basilisp.user=> true
true
 
basilisp.user=> false
false
Poznámka: pozor ovšem na to, že se true a false musí zapisovat s malým písmenem na začátku, na rozdíl od Pythonu:
basilisp.user=> True
 
  exception: <class 'basilisp.lang.compiler.exception.CompilerException'>
      phase: :analyzing
    message: unable to resolve symbol 'True' in this context
       form: True
   location: <REPL Input>:1

Číselné literály jsou již z pohledu programátora mnohem zajímavější, protože numerické hodnoty lze reprezentovat různým způsobem, využívat různé číselné soustavy, pracovat s racionálními čísly atd.

Základem je zápis literálu představujícího celé číslo (odpovídající konvencím zápisu podle Céčka, C++ či Javy):

basilisp.user=> 42
 
42

Před numerickou hodnotu lze zapsat i základ číselné soustavy (konkrétně před r může být uvedeno číslo 2 až 36):

basilisp.user=> 2r101010
42
 
basilisp.user=> 16r2a
42
 
basilisp.user=> 36r16
42

Různé zápisy numerických hodnot s plovoucí řádovou čárkou, interně se hodnoty ukládají podle normy IEEE 754 (vlastně stejně, jako je tomu i v Pythonu):

basilisp.user=> 3.14
3.14
 
basilisp.user=> 1e10
10000000000
 
basilisp.user=> 1e-10
1e-10

Mnohé LISPovské programovací jazyky podporují práci se zlomky, resp. přesněji řečeno s racionálními čísly. Stejně tak je tomu i v jazyce Basilisp:

basilisp.user=> 100/3
100/3

Výpočet, jehož výsledkem je numerická hodnota (zjednodušený zlomek):

basilisp.user=> (+ 7/6 3/4)
23/12

Od Clojure jsou odvozeny i numerické typy představující neomezené hodnoty a typ s neomezenou přesností i rozsahem:

basilisp.user=> 1234M
1234
 
basilisp.user=> 1234N
1234

A konečně se setkáme s hodnotou nil, která v LISPovských jazycích nahrazuje None/NULL:

basilisp.user=> nil
nil

Pozor ovšem na to, že hodnota None z Pythonu není podporována – namísto ní se vždy použije nil:

basilisp.user=> None
 
  exception: <class 'basilisp.lang.compiler.exception.CompilerException'>
      phase: :analyzing
    message: unable to resolve symbol 'None' in this context
       form: None
   location: <REPL Input>:1
Poznámka: V případě nil se nejedná o žádnou novinku, protože nil najdeme i v dalších programovacích jazycích. Poprvé se, i když v poněkud jiném významu, objevil v původním Lispu a jazycích od něho odvozených (Scheme, Clojure); najdeme ho i v programovacím jazyce Lua či v klasickém Pascalu. V některých dalších programovacích jazycích se objevují jiná označení pro neznámou či nulovou hodnotu; typicky se jedná o identifikátory NULL, null a taktéž None. V následující tabulce se pro zajímavost můžete podívat, jaký je vznik a význam všech těchto názvů:
Slovo Původ Význam
null latina ne+ullus, žádný
nil latina nihil, nic (též zkratka „Not In List“)
none stará angličtina ne+an, ani jeden

7. Symboly a hesla

Nejjednodušší typ formy – literály – jsme si již popsali v předchozí kapitole, takže se pojďme věnovat dalším třem typům forem. Druhým typem formy podporovaným programovacím jazykem Basilisp jsou takzvané symboly známé už z klasického LISPu (i Clojure), ke kterým se v Basilisp ještě přidávají keywords. Začněme s popisem „keywords“. Překlad tohoto slova je poněkud problematický kvůli jeho dvojímu významu (alespoň v programování), takže se pokusím používat sousloví „klíčová hesla“, protože termín „keywords“ v Basilisp neznamená, že by se jednalo o rezervovaná klíčová slova jazyka. Klíčová hesla jsou na použití jednodušší než symboly, protože se ve smyčce REPL vyhodnocují samy na sebe a nemůže jim být přiřazena žádná hodnota.

Zbývá odpovědět na otázku, k jakým účelům se tedy vlastně v praxi tento typ formy hodí? Jedním z důvodů zavedení tohoto typu formy do programovacího jazyka Basilisp byla podpora pro velmi užitečný datový typ (kolekce) nazvaný mapa, ve které je možné uchovávat dvojice klíč:hodnota. A jako klíč jsou s výhodou používána právě klíčová hesla, protože jejich hodnotu nelze měnit a navíc se jejich hešovací hodnota může vypočítat pouze jedenkrát. Smyčka REPL pozná, že uživatel používá klíčové heslo z toho, že je těsně před ním napsána dvojtečka. Jak již bylo řečeno výše, vyhodnotí se heslo na sebe samu (což je odlišné od řetězců, které se v jiných ohledech s hesly v mnoha ohledech podobají):

basilisp.user=> :x
:x
 
basilisp.user=> :heslo
:symbol
 
basilisp.user=> :dalsi-heslo
:dalsi-heslo
 
basilisp.user=> :dalsi.heslo
:dalsi.heslo
Poznámka: ve skutečnosti je dvojtečka uváděná před klíčovým heslem jen syntaktickým cukrem, protože „plný“ zápis (v tomto případě speciální) formy představující klíčové heslo vypadá takto:
basilisp.user=> (keyword "heslo")
:heslo
basilisp.user=> (doc keyword)
------------------------
basilisp.core/keyword
([name] [ns name])
  Create a new keyword with ``name`` and optional namespace ``ns``\. Keywords will
  have the colon prefix added automatically, so it should not be provided.
 
  ``name`` may be keyword, symbol, or string. If ``name`` is a keyword or symbol with a
  namespace, the namespace will be included in the resulting value. If ``name`` is a
  string with at least one '/', the string will be split on the first '/' character
  with the first segment being used as ``ns`` and the second as ``name``.
 
  If ``ns`` is not ``nil``, then both ``name`` and ``ns`` must be strings.

Podobným typem formy jsou symboly, před jejichž jménem se používá ampersand. Symbolům může být přiřazena hodnota a z tohoto důvodu se používají pro pojmenování funkcí, proměnných či jmenných prostorů. Se symboly se ještě v tomto článku několikrát setkáme, nyní si tedy jen ukažme, jak se symboly zapisují a jakým způsobem je interaktivní smyčka REPL vyhodnotí:

basilisp.user=> 'symbol
symbol
 
basilisp.user=> 'dalsi-symbol
dalsi-symbol
Poznámka: povšimněte si, že po vyhodnocení v REPL „zmizí“ apostrof původně uvedený před jménem symbolu.

Podobně jako dvojtečka byla pouze syntaktickým cukrem pro speciální formu (keyword „xxx“), je i ampersand zkrácenou podobou speciální formy (quote symbol). Předchozí příklad by tedy šel zapsat i následujícím způsobem:

basilisp.user=> (quote symbol)
symbol

To, že se v obou případech jedná skutečně o stejný symbol, lze zjistit s využitím funkce ekvivalence (zde již trošku předbíháme, takže se prosím k příkladu vraťte po dočtení celého článku):

basilisp.user=> (= 'symbol (quote symbol))
true

Zatím je to poměrně nuda, že? Ale už se pomalu dostáváme k další dvojici forem – složeným formám a speciálním formám – jejichž vyhodnocování představuje srdce programovacího jazyka Basilisp.

8. Složené formy: strukturované datové typy

V této kapitole si popíšeme takzvané složené formy, protože právě tyto formy představují, společně s formami speciálními, jeden z nejdůležitějších prvků programovacího jazyka Basilisp (a do jisté míry je to podobné i u původního LISPu)). V tradičním LISPu je složenou formou především seznam (list), což je ovšem jen zjednodušeně zapsaný řetězec takzvaných tečka-dvojic. Koncept tečka-dvojic byl v Clojure a tím pádem i v Basilispu opuštěn (samotný znak tečky zde dostal jiný význam – volání metod), ovšem k seznamům navíc přibyly i další způsoby zápisu složených forem, které se používají (opět v podstatě jako syntaktický cukr) pro zápis následujících datových struktur: vektoru (vector), množiny (set) a mapy (map).

Všechny čtyři typy složených forem (budeme je dále nazývat kolekce), ať již se jedná o seznam, vektor, množinu či mapu, jsou při svém zápisu do zdrojového kódu z obou stran uvozeny závorkami, přičemž musí být zachována párovost závorek (ke každé otevírací závorce přísluší jedna závorka uzavírací), která je kontrolována před vyhodnocením složené formy ve smyčce REPL.

V předchozím textu bylo napsáno, že základním typem složené formy je seznam (list), jehož prvky se již tradičně (více než padesát let!) zapisují do kulatých závorek. Pro zápis vektorů (vector) se používají hranaté závorky, mapy (map) využívají závorky složené a množiny (set) taktéž závorky složené, ovšem před otevírací závorkou se musí napsat křížek (hash, #). V následující tabulce jsou vypsány všechny čtyři typy složených forem. Kromě seznamů lze ostatní tři složené formy (vektory, mapy, množiny) vytvořit i pomocí vhodného konstruktoru (třetí sloupec), ovšem přesný význam tohoto zápisu si uvedeme až v následujících kapitolách:

Typ kolekce Zápis (syntaktický cukr) Konstruktor
Seznam (prvky) (list prvky)
Vektor [prvky] (vector prvky)
Mapa {dvojice klíč-hodnota} (hash-map dvojice klíč-hodnota)
Množina #{unikátní prvky} (hash-set unikátní prvky)

Konstruktory všech čtyř strukturovaných datových typů mají i svoji (velmi stručnou) nápovědu:

basilisp.user=> (doc list)
------------------------
basilisp.core/list
([& args])
  Create a list from the arguments.
 
basilisp.user=> (doc vector)
------------------------
basilisp.core/vector
([& elems])
  Create a vector from the input arguments.
nil
 
basilisp.user=> (doc hash-map)
------------------------
basilisp.core/hash-map
([& kvs])
  Create a hash map from pairs of input arguments.
nil
 
basilisp.user=> (doc hash-set)
------------------------
basilisp.core/hash-set
([& members])
  Create a set from the input arguments.
nil

9. Příklady konstrukce kolekcí v programovacím jazyku Basilisp

V tabulce zobrazené v předchozí kapitole byl obsah všech čtyř typů kolekcí popsán jen velmi vágně slovem „prvky“. Z tohoto důvodu bude čtenáře tohoto článku více zajímat, jaké prvky v nich mohou být skutečně uloženy. Může se jednat jak o literály (popsané v předchozích kapitolách), symboly, klíčová hesla, tak i – což je nejzajímavější – o jiné kolekce. Není tedy vůbec neobvyklé pracovat například se seznamy uloženými v jiných seznamech, s mapami (v podstatě se strukturami či záznamy), v nichž jsou uloženy vektory atd. Vzhledem k tomu, že Basilisp je dynamicky typovaným programovacím jazykem, lze v jakémkoli okamžiku získat typ každého prvku uloženého v kolekci. Jak se to ve skutečnosti provádí si vysvětlíme v části věnované predikátům. Podívejme se nyní na několik demonstračních příkladů, kde u každého příkladu bude vysvětleno, co se vlastně provádí a z jakého důvodu Basilisp některý typ formy nedokáže zpracovat.

Před seznamy se musí zapsat znak quote, jinak by došlo k jejich vyhodnocení, jakoby se jednalo o zápis volání funkce. Seznamy pochopitelně mohou být vnořené:

basilisp.user=> '(1 2 3)
(1 2 3)
 
basilisp.user=> '(1 2 '(3 '(5 6) 7 8) 9 10)
(1 2 (quote (3 (quote (5 6)) 7 8)) 9 10)

Další seznamy:

basilisp.user=> '('toto 'je 'seznam 'symbolů)
((quote toto) (quote je) (quote seznam) (quote symbolů))
 
basilisp.user=> '("toto" "je" "seznam" "řetězců")
("toto" "je" "seznam" "\u0159et\u011bzc\u016f")

Vektory resp. prvky vektorů se zapisují do hranatých závorek. Zde se naopak znak quote nikdy nepoužívá:

basilisp.user=> [1 2 3]
[1 2 3]
 
basilisp.user=> '(1 2 '(3 4 '(5 6) 7 8) 9 10)
(1 2 (quote (3 4 (quote (5 6)) 7 8)) 9 10)
 
basilisp.user=> [1 2 [3 4 [5 6] 7 8] 9 10]
[1 2 [3 4 [5 6] 7 8] 9 10]

Prázdný seznam a prázdný vektor se zapisuje takto:

basilisp.user=> '()
()
 
basilisp.user=> ()
()
 
basilisp.user=> []
[]

Zápis množiny:

basilisp.user=> #{1 2 3 4}
#{1 2 3 4}

Nebo:

basilisp.user=> #{:i :toto :je :množina}
#{:je :toto :i :množina}

Prázdná množina:

basilisp.user=> {}
{}

Pozor ovšem na to, že prvky množiny musí být unikátní:

basilisp.user=> #{1 2 1 3 2 3 3 4}
 
  exception: <class 'basilisp.lang.reader.SyntaxError'>
    message: Duplicated values in set: 1, 2, 3
       line: 1:18

A konečně se podívejme na zápis slovníku neboli asociativního pole:

basilisp.user=> {:prvni 1 :druhy 2}
{:prvni 1 :druhy 2}
 
basilisp.user=> {:seznam '(:toto :je :seznam), :vektor [:toto :je :vektor] }
{:seznam (:toto :je :seznam) :vektor [:toto :je :vektor]}

Prázdný slovník:

basilisp.user=> #{}
#{}

Načtení obsahu souboru typu JSON do slovníku (zde nepatrně předbíháme):

basilisp.user=> (import basilisp.json)
 
basilisp.user=> (basilisp.json/read (open "configuration.json" "r"))
{"llama_stack" {"url" "http://localhost:8321" "api_key" "**********" "use_as_library_client" false "library_client_config_path" nil} "service" {"port" 8080 "access_log" true "auth_enabled" false "tls_config" {"tls_key_password" nil "tls_certificate_path" nil "tls_key_path" nil} "color_log" true "host" "0.0.0.0" "workers" 1} "name" "Lightspeed Core Service (LCS)"}

Ještě nepatrně složitější příklad:

basilisp.user=> (basilisp.pprint/pprint (basilisp.json/read (open "configuration.json" "r")))
 
{"llama_stack"
 {"url" "http://localhost:8321" "api_key" "**********" "use_as_library_client"
                                                       false
  "library_client_config_path" nil}
 "service"
 {"port" 8080
  "access_log" true
  "auth_enabled" false
  "tls_config" {"tls_key_password" nil
                "tls_certificate_path" nil
                "tls_key_path" nil}
  "color_log" true
  "host" "0.0.0.0"
  "workers" 1}
 "name" "Lightspeed Core Service (LCS)"}
nil

10. Operace s kolekcemi a nekonečnými sekvencemi

Všechny čtyři typy kolekcí popsaných v předchozích dvou kapitolách, mají několik společných vlastností, které umožňují, aby se v programovacím jazyku Basilisp mohly poměrně snadno vytvářet vícevláknové programy. Základní vlastností společnou všem čtyřem typům kolekcí je jejich neměnitelnost (immutability). To znamená, že již ve chvíli, kdy je kolekce vytvořena, je po celou další dobu její existence v běžícím programu určen její obsah, tj. hodnoty všech prvků kolekce. Na první pohled to sice možná může vypadat zvláštně, ale i s takto se chovajícími kolekcemi je možné v reálným programech pracovat a to dokonce často velmi efektivním způsobem. Ostatně i ve standardní knihovně programovacího jazyka Python existují některé třídy, jejichž instance jsou neměnné. Typickým a všeobecně známým příkladem jsou řetězce představované třídou string.

Kromě neměnitelnosti (immutability) je další společnou vlastností všech čtyř typů kolekcí jejich persistence. Většina standardních funkcí poskytovaná programovacím jazykem Basilisp se totiž snaží o to, aby jednou vytvořené sekvence (dejme tomu seznam) byly znovupoužity i v případě, že je vytvořen nový seznam, který v sobě obsahuje i seznam starší (ten stále existuje a mohou na něj existovat reference používané například i v jiných paralelně či souběžně běžících vláknech).

Vzhledem k tomu, že se obsah starého seznamu nemůže změnit (seznam je neměnitelný), může například funkce cons známá již z LISPu jednoduše k seznamu přidat nový první prvek (head) s tím, že tento prvek ukazuje na původní seznam – jinými slovy není nutné, alespoň v tomto případě, vytvářet kopii (ať již plytkou či hlubokou) původního seznamu, což přispívá k tomu, že mnohé operace nad kolekcemi jsou ve skutečnosti velmi rychlé, i když by se podle jejich popisu mohlo zdát, že jejich implementace vyžaduje provedení časově složitých operací (nebo přesunů bloků dat v paměti).

Podobně funkce pop, kterou skalní LISPaři pravděpodobně znají pod názvem cdr, vrátí „nový“ seznam vytvořený z původního seznamu takovým způsobem, že se z něj „odstraní“ první prvek. Ve skutečnosti se však žádný nový seznam nevytváří a již vůbec se nikde žádný prvek neodstraňuje, pouze se jednoduše vrátí reference na druhý prvek původního seznamu, popř. prázdný seznam (), pokud žádný druhý prvek v seznamu uložen není:

basilisp.user=> (pop [1 2 3])
[1 2]

Podobnou operaci lze provést i s vektory:

basilisp.user=> (pop '(1 2 3))
(2 3)

Další operace s kolekcemi:

basilisp.user=> (peek '(1 2 3))
1
basilisp.user=> (peek [1 2 3])
3

S kolekcemi lze pracovat i jako by se jednalo o sekvence:

basilisp.user=> (first '(1 2 3))
1
basilisp.user=> (first [1 2 3])
1

Třetí společnou vlastností všech čtyř typů kolekcí je to, že se v každém případě vždy správně vyhodnotí jejich ekvivalence či neekvivalence, nezávisle na tom, jakým způsobem kolekce vznikla. Programovací jazyk Basilisp v tomto případě ovšem nemůže pouze jednoduše porovnat rovnost referencí ukazujících na porovnávané kolekce (například dva seznamy), ale mnohdy musí rekurzivně procházet jak samotnými porovnávanými kolekcemi, tak i jejich prvky, jež taktéž mohou být kolekcemi. Naproti tomu například v Javě to není vždy tak jednoduché, jak by se možná mohlo na první pohled zdát, protože porovnání dvou objektů vyžaduje překrytí metody Object.equals() a tím pádem i detailní znalost interních struktur porovnávaných objektů.

Kolekce lze spojovat do nové kolekce. K tomuto účelu se používají funkce cons (konstruktor) a conj. Ty se od sebe liší podle použité kolekce i pořadím parametrů:

basilisp.user=> (cons 1 [2 3 4])
(1 2 3 4)
basilisp.user=> (conj [1 2 3] 4)
[1 2 3 4]

Ovšem u seznamů se výsledky conj liší!:

basilisp.user=> (cons 1 '(2 3 4))
(1 2 3 4)
basilisp.user=> (conj '(1 2 3) 4)
(4 1 2 3)

Seznam (kolekce) může vzniknout i jako výsledek dalších operací, například:

Aplikace funkce na všechny prvky zdrojové kolekce:

basilisp.user=> (map inc '(1 2 3 4 5 6 7 8))
(2 3 4 5 6 7 8 9)

Aplikace funkce postupně na všechny n-tice získané ze zdrojových kolekcí:

basilisp.user=> (map * [1 2 3 4] [5 6 7 8])
(5 12 21 32)

Dtto:

basilisp.user=> (map / (range 10) (range 1 10))
(0 1/2 2/3 3/4 4/5 5/6 6/7 7/8 8/9)

Pracovat je možné i s nekonečnými sekvencemi, které se vyhodnocují líně:

basilisp.user=> (doc take)
------------------------
basilisp.core/take
([n] [n coll])
  Return the first ``n`` elements of ``coll``\.

Použití této funkce na nekonečné vstupní sekvence:

basilisp.user=> (take 5 (repeat "x"))
("x" "x" "x" "x" "x")

I (range) je generátorem nekonečné sekvence hodnot:

basilisp.user=> (take 10 (range))
(0 1 2 3 4 5 6 7 8 9)

Naproti tomu (range x y) vytváří konečnou sekvenci hodnot:

basilisp.user=> (defn factorial
                [n]
                (reduce * (range 1 (inc n))))
#'basilisp.user/factorial
 
basilisp.user=> (factorial 3)
6
 
basilisp.user=> (factorial 100)
9332621544394415268169923885626670049071
5968264381621468592963895217599993229915
6089414639761565182862536979208272237582
51185210916864000000000000000000000000

Otestování funkce pro výpočet faktoriálu:

basilisp.user=> (dotimes [n 10] (println n (factorial n)))
0 1
1 1
2 2
3 6
4 24
5 120
6 720
7 5040
8 40320
9 362880
nil

11. Predikáty, zjištění typových informací za běhu

Predikáty jsou funkce vracející pravdivostní hodnotu true nebo false. V některých variantách programovacího jazyka LISP bylo zvykem za jméno predikátu dávat znak „p“, takže například funkce/predikát pro test na nulovou hodnotu (velmi často používaný predikát) měl název zerop. V programovacím jazyku Basilisp se namísto znaku „p“ používá otazník, protože i otazník může být součástí názvu identifikátoru. V následující tabulce jsou vypsány základní predikáty:

# Predikát Význam
1 nil? test, zda je předaná hodnota rovna literálu nil
2 true? test, zda je předaná hodnota rovna literálu true
3 false? test, zda je předaná hodnota rovna literálu false
4 number? test na číslo (libovolného typu)
5 integer? test na celé číslo
6 ratio? test na zlomek (nikoli na obecné desetinné číslo)
7 float? test na desetinné číslo
8 decimal? test na hodnotu typu BigDecimal
9 even? test na sudou hodnotu
10 odd? test na lichou hodnotu
11 pos? test na kladnou hodnotu
12 neg? test na zápornou hodnotu
13 zero? test na nulu
14 keyword? test, zda je předaná hodnota typu klíčové heslo
15 symbol? test, zda je předaná hodnota typu symbol
16 char? test, zda je předaná hodnota typu char
17 string? test, zda je předaná hodnota typu řetězec
18 seq? test, zda je předaná hodnota typu sekvence

Příklady volání predikátů:

basilisp.user=> (nil? nil)
true
 
basilisp.user=> (nil? '())
false
 
basilisp.user=> (nil? ())
false
 
basilisp.user=> (neg? -42)
true
 
basilisp.user=> (neg? 42)
false
 
basilisp.user=> (ratio? 1/2)
true
 
basilisp.user=> (ratio? 1)
false

V některých případech je důležité zjistit typ hodnoty, a to za běhu aplikace. K tomuto účelu lze použít funkci type známou přímo z Pythonu. Příklady volání této funkce:

basilisp.user=> (type nil)
<class 'NoneType'>
 
basilisp.user=> (type true)
<class 'bool'>
 
basilisp.user=> (type 'symbol)
<class 'basilisp.lang.symbol.Symbol'>
 
basilisp.user=> (type :heslo)
<class 'basilisp.lang.keyword.Keyword'>
 
basilisp.user=> (type '())
<class 'basilisp.lang.list.PersistentList'>
 
basilisp.user=> (type [])
<class 'basilisp.lang.vector.PersistentVector'>
 
basilisp.user=> (type #{})
<class 'basilisp.lang.set.PersistentSet'>
 
basilisp.user=> (type {})
<class 'basilisp.lang.map.PersistentMap'>
Poznámka: povšimněte si, že seznamy, vektory, množiny i slovníky jsou perzistentními datovými strukturami.

12. Řídicí struktury (speciální formy a makra)

Programovací jazyk Basilisp nabízí programátorům několik základních řídicích struktur, které jsou představovány takzvanými speciálními formami (ty se vyhodnocují jinak, než běžné funkce, proto jsou ostatně nazývány „speciální“). Jedná se především o formy se jmény if, loop a recur. Ovšem díky makrosystému, tedy možnosti tvorby uživatelských maker, můžeme v aplikacích psaných v Basilispu použít mnohem více řídicích struktur, které jsou interně postaveny právě na výše zmíněné trojici (celý Basilisp je, podobně jako jeho ideový předchůdce jazyk Clojure, stavebnicí s malým množstvím základních prvků). V následující tabulce jsou vypsány některé z nich (prozatím se soustředíme na rozhodování a rozvětvení toku programu):

# Konstrukce Typ Stručný popis
1 if speciální forma základní rozhodovací konstrukce, základ pro další makra
2 if+do dvě speciální formy použito ve chvíli, kdy je nutné do jedné větve či obou větví zapsat více výrazů
3 if-let makro kombinace speciálních forem if a let
4 if-some makro kombinace speciálních forem if (test na nil) a let
       
5 and makro postupné vyhodnocování předaných výrazů až do chvíle, kdy se vrátí nil či false (jediné „nepravdy“)
6 or makro postupné vyhodnocování předaných výrazů až do chvíle, kdy se vrátí true
       
7 when makro vhodná náhrada za if s jedinou větví s více výrazy
8 when-not makro vhodná náhrada za if-not s jedinou větví s více výrazy
9 when-let makro kombinace speciálních forem when a let
10 when-some makro kombinace speciálních forem when (test na nil) a let
11 when-first makro použito při testu prvního prvku sekvence s následným zpracováním sekvence
       
12 cond makro postupné testování podmínek, pokud je podmínka splněna, vrátí se hodnota příslušného výrazu
13 cond + :else makro typické použití makra cond s větví :else nebo :default
14 condp makro postupné dosazování testované hodnoty do zadaného výrazu, obdoba switch-case
       
15 cond-> makro odvozeno od cond, bude popsáno příště
16 cond->> makro odvozeno od cond, bude popsáno příště
       
17 case makro další forma realizace rozvětvení
Poznámka: při studiu výše zmíněných forem se vývojáři mohou přiučit i to, jak vlastně interně pracuje makrosystém programovacího jazyka Basilisp. Tímto tématem jsme se částečně zabývali zde v kontextu jazyka Clojure, ale prakticky totéž platí i pro Basilisp.

Pro mnoho z výše uvedených forem je k dispozici i nápověda:

basilisp.user=> (doc if-let)
------------------------
basilisp.core/if-let
([&env &form binding true-cond false-cond])
  Evaluate the binding as with ``let``, binding the given name for use in the ``true``
  expression iff the binding expression is truthy . Otherwise, return the ``false``
  expression without binding the name.
nil
basilisp.user=> (doc case)
------------------------
basilisp.core/case
([&env &form expr & clauses])
  Switch on ``expr`` to return a matching clause from the set of input clauses.
 
  The input expression may be any valid Basilisp expression. A single default expression
  can follow the clauses, and its value will be returned if no clause matches.
 
  The clauses are pairs of a matching value and a return value. The matching values are
  not evaluated and must be compile-time constants. Symbols will not be resolved. Lists
  may be passed to match multiple compile time values to a single return value. The
  dispatch is done in constant time.
nil
basilisp.user=> (doc cond->>)
------------------------
basilisp.core/cond->>
([&env &form x & clauses])
  Takes a test and form pair, threading ``x`` (as by :lpy:fn:`->>`) through each form
  for which the corresponding test evaluates as ``true``\. ``cond->>`` does not short
  circuit evaluation in any case.
nil

13. Ukázky využití vybraných řídicích struktur

Všechna makra popsaná v dalším textu jsou založena na využití speciální formy if, jejíž různé varianty si popíšeme v této kapitole.

Nejprve vytvoříme několik jmen navázaných na hodnoty (což je v programovacím jazyku Basilisp obdoba konstant). Tyto hodnoty budou použity v podmínkách uvedených později:

(def x 10)
(def y 20)
(def z 20)
Poznámka: v naprosté většině skutečných aplikací by se def tímto způsobem nepoužívalo, nebo alespoň ne frekventovaně, protože to vede k vytvoření obdoby hodnot dostupných „globálně“ v rámci celého jmenného prostoru.

Základní rozhodovací konstrukce je tvořena speciální formou if, která existuje ve dvou variantách – pouze s větví then a s oběma větvemi thenelse. Tuto speciální formu lze tedy zapsat ve zkrácené podobě:

(if test větev-then)

nebo v plné podobě:

(if test větev-then větev-else)

Speciální formu if je možné použít ve formě rozvětvení, což je konstrukce známá například z programovacích jazyků C, Go, Pascalu, Pythonu atd. V tomto případě se (nyní již v Basilisp) typicky setkáme s funkcemi nebo makry s vedlejším efektem, které jsou ve větvi then použity:

(if (< x y)
  (println "x < y"))
 
x < y
nil

V programovacím jazyku Basilisp a současně i ve všech LISPovských programovacích se speciální forma if vyhodnocuje a následně se vrátí výsledek tohoto vyhodnocení. Pokud je podmínka splněna, je vrácena hodnota funkce/makra ve větvi then, v opačném případě je vrácena hodnota funkce/makra ve větvi else nebo nil tehdy, pokud větev else není vůbec zapsána:

(if (< x y)
  (+ x y))
 
30

Nebo ještě jednodušeji:

(if (< x y)
  :mensi)
 
:mensi

Následující konstrukce vrátí hodnotu nil, protože podmínka není splněna a současně není zapsána větev else:

(if (< y x)
  (+ x y))
 
nil

resp:

(if (> x y)
  :vetsi)
 
nil

Zápis s oběma větvemi:

(if (< x y)
  (println "x < y")
  (println "x > y"))
 
x < y
nil

Konstrukce if je možné vnořovat:

(if (zero? x)
  :nulove
  (if (neg? x)
    :zaporne
    :kladne))

Praktičtější příklad – výpočet největšího společného dělitele:

(defn gcd
  [x y]
  (if (= x y)
    x
    (if (> x y)
      (gcd (- x y) y)
      (gcd x (- y x)))))
 
(println (gcd 64 24))
8
nil
Poznámka: nyní se nám ve zdrojovém kódu „hromadí“ kulaté závorky :-)

V tomto případě je však lepší použít konstrukci cond popsanou níže.

Mnohdy se setkáme s požadavkem, že se v jedné větvi speciální formy if popř. v obou větvích má použít více funkcí s vedlejším efektem (volání více funkcí bez vedlejšího efektu nemá význam, i když není zakázáno). Tento požadavek, který je v Algolských programovacích jazycích (C, Pascal, JavaScript, Go, …) vyřešen s využitím programových bloků (složené závorky), by bylo možné otrocky přepsat do jazyka Basilisp pomocí speciální formy do:

(if (< x y)
  (do
    (println "x < y")
    :mensi)
  (do
    (println "x > y")
    :vetsi))

Ve skutečnosti je však výše zmíněná kombinace if + do velmi špatně čitelná, nehledě na to, že se kód začíná ztrácet ve velkém množství kulatých závorek. Existuje však i (pro mnoho účelů) lepší řešení. Pokud konstrukce if obsahuje pouze jedinou větev (předpokládejme nyní pro určité zjednodušení, že se jedná o větev then), lze namísto speciální formy if použít makro nazvané příznačně when:

basilisp.user=> (doc when)
------------------------
basilisp.core/when
([&env &form cond & body])
  Evaluate ``cond`` and if it is truthy, execute body in an implicit ``do`` block.
nil

Následuje ukázka příkladu použití tohoto makra v situaci, kdy se má při splnění podmínky vykonat více funkcí (s vedlejším efektem) a navíc se má vrátit nějaká hodnota, typicky s využitím funkce bez vedlejšího efektu:

(when (< x y)
  (println "----------")
  (println "x < y")
  (println "----------")
  :mensi)
 
x < y
:mensi

Následuje nepatrně složitější příklad vracející výsledek funkce +:

(when (< x y)
  (println "----------")
  (println "x < y")
  (println "----------")
  (+ x y))
 
x < y
30

Blok vykonaný pro opačnou podmínku se zapisuje formou when-not:

basilisp.user=> (doc when-not)
------------------------
basilisp.core/when-not
([&env &form cond & body])
  Evaluate ``cond`` and if it is falsey, execute body in an implicit ``do`` block.
nil

14. Konstrukce cond a condp

Všechny rozhodovací konstrukce popsané v předchozí kapitole prováděly rozvětvení toku programu na základě vyhodnocení jediné podmínky. Ovšem v praxi se velmi často setkáme s nutností rozhodovat se na základě většího množství podmínek popř. na základě většího množství hodnot (a obecně pak na základě pattern matchingu, což si ukážeme příště). Pokud je nutné provést rozhodnutí na základě více podmínek, nabízí se využití makra nazvaného cond, které se mj. objevilo (i když jinak zapisované) už v prvních verzích LISPu:

basilisp.user=> (doc cond)
------------------------
basilisp.core/cond
([&env &form & clauses])
  Given groups of test/expression pairs, evaluate each test and, if ``true``\, return
  the expression. Otherwise, continue through until reaching the final expression.
nil

Tomuto makru se předávají dvojice test+výraz. Pokud je test splněn, je vrácena hodnota příslušného výrazu. Poslední test bývá zapsán formou symbolu, který se vždy vyhodnotí na pravdu – což je vlastně jakýkoli symbol rozdílný od false nebo nil. Typicky se používá symbol :else, ovšem někteří vývojáři dávají přednost :default (takže se jedná o céčkaře nebo Javisty :-).

Funkci pro výpočet znaménka lze s využitím makra cond přepsat následujícím způsobem:

(defn sgn-3
  [x]
  (cond (pos? x) 1
        (neg? x) -1
        true 0))

Otestování funkcionality takto upravené funkce je snadné:

(doseq [value [-100 -1 0 1 100]]
        (println (sgn-3 value)))

Se shodnými výsledky, jako tomu bylo v předchozích příkladech:

-1
-1
0
1
1

Poslední test se ovšem většinou zapisuje symbolem :else:

(defn sgn-4
  [x]
  (cond (pos? x)  1
        (neg? x) -1
        :else     0))

nebo :default:

(defn sgn-5
  [x]
  (cond (pos? x)  1
        (neg? x) -1
        :default  0))

Přepis funkce pro výpočet největšího společného dělitele:

(defn gcd-2
  [x y]
  (cond
    (= x y) x
    (> x y) (gcd-2 (- x y) y)
    :else   (gcd-2 x (- y x))))

S otestováním:

(println (gcd-2 64 24))
8
nil
 
(println (gcd-2 123456 6543216))
48
nil

Pokusme se nyní výraz s makrem cond expandovat, abychom zjistili, jaký kód bude vlastně přeložen do bajtkódu:

(macroexpand
  '(cond (pos? x)  1
         (neg? x) -1
         :else     0))

Výsledkem expanze bude:

(if (pos? x) 1 (basilisp.core/cond (neg? x) -1 :else 0))

Plná expanze makra:

basilisp.user=> (macroexpand-all
                  '(cond (pos? x)  1
                         (neg? x) -1
                         :else     0))

Výsledek už bude obsahovat jen vnořenou speciální formu if:

(if (pos? x) 1 (if (neg? x) -1 (if :else 0 nil)))

Pro zajímavost si vyzkoušejme expanzi složitějšího výrazu, který převádí bodové ohodnocení na známky:

(let [grade 85]
  (cond
    (>= grade 90) "A"
    (>= grade 80) "B"
    (>= grade 70) "C"
    (>= grade 55) "D"
    :else         "F"))

Expanze:

basilisp.user=> (macroexpand
                  '(cond
                    (>= grade 90) "A"
                    (>= grade 80) "B"
                    (>= grade 70) "C"
                    (>= grade 55) "D"
                    :else "F"))

Výsledek:

(if (>= grade 90) "A" (basilisp.core/cond (>= grade 80) "B" (>= grade 70) "C" (>= grade 55) "D" :else "F"))

Plná expanze"

basilisp.user=> (macroexpand-all
                  '(cond
                    (>= grade 90) "A"
                    (>= grade 80) "B"
                    (>= grade 70) "C"
                    (>= grade 55) "D"
                    :else "F"))

Výsledek bude opět obsahovat jen vnořenou speciální formu if:

(if (>= grade 90) "A" (if (>= grade 80) "B" (if (>= grade 70) "C" (if (>= grade 55) "D" (if :else "F" nil)))))

Výše popsané makro cond je velmi univerzální, protože každý test (kterých může být libovolné množství) je realizován plnohodnotným predikátem, tj. funkcí, na základě jejíž (pravdivostní) návratové hodnoty se rozhoduje, jestli se má provést příslušná větev či zda se má vyzkoušet další test. Ve výsledku je toto makro expandováno na vnořené speciální formy if. Ovšem mnohdy takovou univerzálnost nepotřebujeme a naopak vyžadujeme, aby se výsledek nějakého výrazu porovnal se sekvencí známých hodnot. Taková konstrukce, která je v C, C++ či Javě realizována přes switch, se v programovacím jazyku Basilisp zapisuje s využitím makra nazvaného condp:

basilisp.user=> (doc condp)
------------------------
basilisp.core/condp
([&env &form pred expr & clauses])
  Take a predicate and an expression and a series of clauses, call ``(pred test expr)``
  on the first expression for each clause. The result expression from first the set of
  clauses for which this expression returns a truthy value will be returned from the
  ``condp`` expression.

  Clauses can take two forms:

  - ``test-expr result-expr``
  - ``test-expr :>> result-fn`` where :>> is a keyword literal

  For the ternary expression clause, the unary ``result-fn`` will be called with the
  result of the predicate.

  A single final expression can be included at the end with no test expression which
  will be returned if no other clause matches the predicate. If no default is provided
  and no clause matches the predicate, a ``ValueError`` will be thrown.
nil

Z popisu je zřejmé, že je nutné uvést část výrazu, do kterého se postupně doplňují hodnoty z testů v jednotlivých větvích – skutečně se tedy jedná o obdobu case z C či Javy. Poslední větev pochopitelně žádnou hodnotu pro otestování neobsahuje.

Podívejme se nyní na základní způsob použití tohoto makra. Na základě předaného řetězce se rozhodneme, jaká hodnota se vrátí (jedná se o primitivní transformaci, která by se v reálném programu realizovala přes mapu):

(let [value (read-line)]
  (condp = value
      "one"   1
      "two"   2
      "three" 3
      "four"  4
      "five"  5
              "unknown value"))
Poznámka: a pak se říká, že v LISPovských jazycích je velké množství závorek – v konstrukci condp je jich naprosté minimum.

Samozřejmě namísto konstant ve větvích můžeme použít nějaký složitější výraz, zde konkrétně volání funkcí +, – atd:

(let [value (read-line)]
  (condp = value
      "one"   (+ 0 1)
      "two"   (+ 1 1)
      "three" 3
      "four"  (* 2 2)
      "five"  5
              (str "unexpected value, \"" value \")))

Výrazy mohou být použity i v testovaných hodnotách (což představuje rozdíl oproti některým výše zmíněným programovacím jazykům):

(let [value (read-line)]
  (condp = value
      "one"           (+ 0 1)
      (str "t" "wo")  (+ 1 1)
      (str "t" "ree") 3
      "four"          (* 2 2)
      "five"          5
                      (str "unexpected value, \"" value \")))
Poznámka: pro jednoduchost jsou všechny příklady z této kapitoly dosti umělé; typicky „školní“.

Expanze condp:

basilisp.user=> (macroexpand-all '(let [value (read-line)]
                  (condp = value
                      "one"   1
                      "two"   2
                      "three" 3
                      "four"  4
                      "five"  5
                              "unknown value")))

Výsledkem je konstrukce postavená na speciální formě if:

(let* [value (.rstrip (.readline *in*))]
    (if (= "one" value)
        1
        (if (= "two" value)
            2
            (if (= "three" value)
                3
                (if (= "four" value)
                    4
                    (if (= "five" value)
                        5
                        "unknown value"))))))

15. Balíčky dodávané se samotným jazykem Basilisp

Společně s Basilispem jsou dodávány i některé balíčky, jejichž jména a do značné míry i obsah je inspirován jazykem Clojure. To zjednodušuje portaci programů, protože vlastně postačuje změnit první hodnotu ve jmenném prostoru z clojure na basilisp:

Jmenný prostor
basilisp.contrib.bencode
basilisp.contrib.nrepl-server
basilisp.core
basilisp.core.protocols
basilisp.data
basilisp.edn
basilisp.io
basilisp.json
basilisp.main
basilisp.pprint
basilisp.process
basilisp.repl
basilisp.set
basilisp.shell
basilisp.stacktrace
basilisp.string
basilisp.template
basilisp.test
basilisp.test.fixtures
basilisp.url
basilisp.walk

Příklad použití funkce z balíčku basilisp.pprint:

basilisp.user=> (use 'basilisp.pprint)
 
basilisp.user=> (pprint (macroexpand-all '(let [value (read-line)]
                  (condp = value
                      "one"   1
                      "two"   2
                      "three" 3
                      "four"  4
                      "five"  5
                              "unknown value"))))
 
(let*
 [value (.rstrip (.readline *in*))]
 (if
  (= "one" value)
  1
  (if
   (= "two" value)
   2
   (if
    (= "three" value)
    3
    (if
     (= "four" value)
     4
     (if (= "five" value) 5 "unknown value"))))))
nil

16. Interoperabilita s Pythonem

Nejdůležitějším rysem Basilispu je jeho schopnost relativně snadno volat kód psaný v Pythonu. Bez této schopnosti by se jednalo „jen“ o další interpret LISPu, kterých vzniklo několik set. Ovšem fakt, že Basilisp může volat jakoukoli funkci Pythonu (z libovolného balíčku) nebo metodu jakékoli třídy, vlastně otevírá celý rozsáhlý ekosystém Pythonu světu LISPu.

Ukažme si tuto schopnost na několika příkladech. Nejdříve načteme standardní Pythonovský balíček datetime (způsobem importu se budeme podrobněji zabývat v další kapitole):

basilisp.user=> (import datetime)
nil

Zavolání funkce now vracející objekt. Do konzole se vypíše tisknutelná podoba tohoto objektu:

basilisp.user=> (datetime.datetime/now)
#inst "2025-11-11T16:18:25.492381"

Objekt (tedy instanci třídy) si můžeme uložit do nové proměnné nazvané například now:

basilisp.user=> (def now (datetime.datetime/now))
#'basilisp.user/now

Ověření, že pracujeme s typem „objekt“:

basilisp.user=> (type now)
<class 'datetime.datetime'>

Můžeme získat i seznam atributů a metod, což není překvapivé, protože dir je původní funkce z Pythonu:

basilisp.user=> (dir now)
#py ["__add__" "__class__" "__delattr__" "__dir__" "__doc__" "__eq__" "__format__"
"__ge__" "__getattribute__" "__getstate__" "__gt__" "__hash__" "__init__"
"__init_subclass__" "__le__" "__lt__" "__ne__" "__new__" "__radd__" "__reduce__"
"__reduce_ex__" "__repr__" "__rsub__" "__setattr__" "__sizeof__" "__str__" "__sub__"
"__subclasshook__" "astimezone" "combine" "ctime" "date" "day" "dst" "fold"
"fromisocalendar" "fromisoformat" "fromordinal" "fromtimestamp" "hour" "isocalendar"
"isoformat" "isoweekday" "max" "microsecond" "min" "minute" "month" "now" "replace"
"resolution" "second" "strftime" "strptime" "time" "timestamp" "timetuple" "timetz"
"today" "toordinal" "tzinfo" "tzname" "utcfromtimestamp" "utcnow" "utcof

Přístup k atributu objektu se provádí možná poněkud neobvykle s využitím lomítka (převzato z Clojure):

basilisp.user=> now/year
2025

Pro volání metody se používá speciální forma zapisovaná tečkou, což je opět neobvyklé:

basilisp.user=> (. now __str__)
"2025-11-11 16:19:00.366118"

Metodu je ovšem možné volat i jako běžnou (pseudo)funkci s tečkou na začátku. Prvním parametrem je instance třídy:

basilisp.user=> (.__str__ now)
"2025-11-11 16:19:00.366118"

Ukázka volání metody, která akceptuje další parametry:

basilisp.user=> (. now strftime "%Y-%m-%d")
"2025-11-11"

Alternativní způsob zápisu:

basilisp.user=> (.strftime now "%Y-%m-%d")
"2025-11-11"

Ještě si musíme ukázat, jak se volají standardní funkce Pythonu, které se jmenují stejně, jako funkce v Basilispu. Příkladem je funkce str:

basilisp.user=> (str 42)
"42"

Původní Pythonovskou funkci str musíme uvést i se jmenným prostorem:

basilisp.user=> (python/str 42)
"42"

Složitější příklad, kde se kombinují standardní funkce Pythonu i standardní funkce Basilispu:

basilisp.user=> (python/str (abs (int "-42")))
"42"

Mimochodem: je zde možné s výhodou použít threading macro (možná se jedná o jeden z nejlepších způsobů, jak se zbavovat závorek ve zdrojových kódech :-):

basilisp.user=> (-> "-42" int abs python/str)
"42"

17. Využití balíčků Pythonu přímo z Basilispu

Z Basilispu je možné volat i funkce z naimportovaných standardních Pythonovských balíčků, popř. přistupovat k proměnným, které jsou v těchto balíčcích definovány.

Balíček je nejdříve nutné naimportovat, a to například následujícím způsobem:

basilisp.user=> (import json)
nil

Poté je možné volat funkce, které jsou v tomto balíčku definovány, a to s využitím konvence (jmenný_prostor/jméno_funkce):

basilisp.user=> (json/dumps (dict {"foo" 1 "bar" 2}))
"{\"foo\": 1, \"bar\": 2}"

Naimportujeme ještě jeden balíček, nyní math:

basilisp.user=> (import math)
nil

Přečtení hodnoty proměnné definované v balíčku (bez závorek, protože nechceme volat funkci):

basilisp.user=> math/pi
3.141592653589793

Zavolání funkce z tohoto balíčku:

basilisp.user=> (math/sqrt 2)
1.4142135623730951

Alternativně je možné definovat jmenný alias, podobně jako je tomu i v samotném Pythonu:

basilisp.user=> (import [math :as m])
nil

Přístup k funkci přes jmenný alias:

basilisp.user=> (m/sqrt 2)
1.4142135623730951

Funkce a proměnné (resp. přesněji řečeno symboly) můžeme zařadit přímo do aktuálního jmenného prostoru:

basilisp.user=> (import [math :refer [pi sqrt]])
nil

Poté se již neuvádí jmenný prostor:

basilisp.user=> pi
3.141592653589793

Nebo:

basilisp.user=> (sqrt 2)
1.4142135623730951
Poznámka: naprosto stejně se přistupuje k importovaným třídám. Jejich instance se konstruují pomocí (new název_třídy parametry_konstruktoru).

18. Předchozí části seriálu o LISPovských programovacích jazycích

V této kapitole jsou uvedeny odkazy na všechny předchozí části seriálu o světě programovacích jazyků LISP a Scheme (kromě samostatného seriálu, který se věnoval programovacímu jazyku Clojure, odkazy na tento seriál jsou uvedeny na konci kapitoly):

  1. Jemný úvod do rozsáhlého světa jazyků LISP a Scheme
    https://www.root.cz/clanky/jemny-uvod-do-rozsahleho-sveta-jazyku-lisp-a-scheme/
  2. PicoLisp: minimalistický a přitom překvapivě výkonný interpret Lispu
    https://www.root.cz/clanky/picolisp-minimalisticky-a-pritom-prekvapive-vykonny-interpret-lispu/
  3. PicoLisp: užitečné funkce a speciální formy používané při tvorbě aplikací
    https://www.root.cz/clanky/picolisp-uzitecne-funkce-a-specialni-formy-pouzivane-pri-tvorbe-aplikaci/
  4. PicoLisp: dokončení popisu a několik praktických rad na závěr
    https://www.root.cz/clanky/picolisp-dokonceni-popisu-a-nekolik-praktickych-rad-na-zaver/
  5. GNU Guile – interpret Scheme vestavitelný do nativních aplikací
    https://www.root.cz/clanky/gnu-guile-interpret-scheme-vestavitelny-do-nativnich-aplikaci/
  6. TinyScheme aneb další interpret jazyka Scheme vestavitelný do dalších aplikací
    https://www.root.cz/clanky/tinyscheme-aneb-dalsi-interpret-jazyka-scheme-vestavitelny-do-dalsich-aplikaci/
  7. Kawa: překvapivě silný a výkonný dialekt Scheme pro JVM
    https://www.root.cz/clanky/kawa-prekvapive-silny-a-vykonny-dialekt-scheme-pro-jvm/
  8. Jazyk Kawa v ekosystému virtuálního stroje Javy
    https://www.root.cz/clanky/jazyk-kawa-v-ekosystemu-virtualniho-stroje-javy/
  9. Zpracování vektorů, matic a N-rozměrných polí v programovacím jazyku Kawa
    https://www.root.cz/clanky/zpracovani-vektoru-matic-a-n-rozmernych-poli-v-programovacim-jazyku-kawa/
  10. Racket: programovací jazyk a současně i platforma pro vývoj nových jazyků
    https://www.root.cz/clanky/racket-programovaci-jazyk-a-soucasne-i-platforma-pro-vyvoj-novych-jazyku/
  11. Makra v Racketu i v dalších lispovských jazycích
    https://www.root.cz/clanky/makra-v-racketu-i-v-dalsich-lispovskych-jazycich/
  12. Základní knihovna jazyka Racket
    https://www.root.cz/clanky/zakladni-knihovna-jazyka-racket/
  13. Jazyk Joker: dialekt Clojure naprogramovaný v Go
    https://www.root.cz/clanky/jazyk-joker-dialekt-clojure-naprogramovany-v-go/
  14. Chicken Scheme – další interpret a především překladač programovacího jazyka Scheme
    https://www.root.cz/clanky/chicken-scheme-dalsi-interpret-a-predevsim-prekladac-programovaciho-jazyka-scheme/
  15. Projekt Gambit – další kvalitní interpret i překladač programovacího jazyka Scheme
    https://www.root.cz/clanky/projekt-gambit-dalsi-kvalitni-interpret-i-prekladac-programovaciho-jazyka-scheme/
  16. Interlisp aneb oživujeme dinosaura
    https://www.root.cz/clanky/interlisp-aneb-ozivujeme-dinosaura/
  17. Propojení světa LISPu se světem JavaScriptu s využitím transpřekladače Wisp
    https://www.root.cz/clanky/propojeni-sveta-lispu-se-svetem-javascriptu-s-vyuzitim-transprekladace-wisp/
  18. Propojení světa LISPu se světem JavaScriptu s využitím transpřekladače Wisp (2.část)
    https://www.root.cz/clanky/propojeni-sveta-lispu-se-svetem-javascriptu-s-vyuzitim-transprekladace-wisp-2-cast/
  19. Common Lisp: žralok mezi programovacími jazyky
    https://www.root.cz/clanky/common-lisp-zralok-mezi-programovacimi-jazyky/
  20. Common Lisp: žralok mezi programovacími jazyky (2.část)
    https://www.root.cz/clanky/common-lisp-zralok-mezi-programovacimi-jazyky-2-cast/
  21. 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/

Články o Elispu:

  1. Úpravy Emacsu a tvorba nových modulů s využitím Emacs Lispu
    https://www.root.cz/clanky/upravy-emacsu-a-tvorba-novych-modulu-s-vyuzitim-emacs-lispu/
  2. Úpravy Emacsu s Emacs Lisp: základní konstrukce jazyka
    https://www.root.cz/clanky/upravy-emacsu-s-emacs-lisp-zakladni-konstrukce-jazyka/
  3. Úpravy Emacsu s Emacs Lisp: všemocné makro cl-loop a knihovna dash
    https://www.root.cz/clanky/upravy-emacsu-s-emacs-lisp-vsemocne-makro-cl-loop-a-knihovna-dash/
  4. Úpravy Emacsu s Emacs Lisp: možnosti nabízené knihovnou Dash
    https://www.root.cz/clanky/upravy-emacsu-s-emacs-lisp-moznosti-nabizene-knihovnou-dash/
  5. Úpravy Emacsu s Emacs Lisp: dokončení popisu Emacs Lispu
    https://www.root.cz/clanky/upravy-emacsu-s-emacs-lisp-dokonceni-popisu-emacs-lispu/
  6. Úpravy Emacsu s Emacs Lisp: manipulace se základními datovými strukturami Emacsu
    https://www.root.cz/clanky/upravy-emacsu-s-emacs-lisp-manipulace-se-zakladnimi-datovymi-strukturami-emacsu/
Poznámka: povšimněte si, jak je svět LISPovských jazyků pestrý.

Seriál o programovacím jazyku Clojure:

  1. Clojure 1: Úvod
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm/
  2. Clojure 2: Symboly, kolekce atd.
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-2-cast/
  3. Clojure 3: Funkcionální programování
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-3-cast-funkcionalni-programovani/
  4. Clojure 4: Kolekce, sekvence a lazy sekvence
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-4-cast-kolekce-sekvence-a-lazy-sekvence/
  5. Clojure 5: Sekvence, lazy sekvence a paralelní programy
    http://www.root.cz/clanky/clojure-a-bezpecne-aplikace-pro-jvm-sekvence-lazy-sekvence-a-paralelni-programy/
  6. Clojure 6: Podpora pro paralelní programování
    http://www.root.cz/clanky/programovaci-jazyk-clojure-6-futures-nejsou-jen-financni-derivaty/
  7. Clojure 7: Další funkce pro paralelní programování
    http://www.root.cz/clanky/programovaci-jazyk-clojure-7-dalsi-podpurne-prostredky-pro-paralelni-programovani/
  8. Clojure 8: Identity, stavy, neměnné hodnoty a reference
    http://www.root.cz/clanky/programovaci-jazyk-clojure-8-identity-stavy-nemenne-hodnoty-a-referencni-typy/
  9. Clojure 9: Validátory, pozorovatelé a kooperace s Javou
    http://www.root.cz/clanky/programovaci-jazyk-clojure-9-validatory-pozorovatele-a-kooperace-mezi-clojure-a-javou/
  10. Clojure 10: Kooperace mezi Clojure a Javou
    http://www.root.cz/clanky/programovaci-jazyk-clojure-10-kooperace-mezi-clojure-a-javou-pokracovani/
  11. Clojure 11: Generátorová notace seznamu/list comprehension
    http://www.root.cz/clanky/programovaci-jazyk-clojure-11-generatorova-notace-seznamu-list-comprehension/
  12. Clojure 12: Překlad programů z Clojure do bajtkódu JVM I:
    http://www.root.cz/clanky/programovaci-jazyk-clojure-12-preklad-programu-z-clojure-do-bajtkodu-jvm/
  13. Clojure 13: Překlad programů z Clojure do bajtkódu JVM II:
    http://www.root.cz/clanky/programovaci-jazyk-clojure-13-preklad-programu-z-clojure-do-bajtkodu-jvm-pokracovani/
  14. Clojure 14: Základy práce se systémem maker
    http://www.root.cz/clanky/programovaci-jazyk-clojure-14-zaklady-prace-se-systemem-maker/
  15. Clojure 15: Tvorba uživatelských maker
    http://www.root.cz/clanky/programovaci-jazyk-clojure-15-tvorba-uzivatelskych-maker/
  16. Programovací jazyk Clojure – triky při práci s řetězci
    http://www.root.cz/clanky/programovaci-jazyk-clojure-triky-pri-praci-s-retezci/
  17. Programovací jazyk Clojure – triky při práci s kolekcemi
    http://www.root.cz/clanky/programovaci-jazyk-clojure-triky-pri-praci-s-kolekcemi/
  18. Programovací jazyk Clojure – práce s mapami a množinami
    http://www.root.cz/clanky/programovaci-jazyk-clojure-prace-s-mapami-a-mnozinami/
  19. Programovací jazyk Clojure – základy zpracování XML
    http://www.root.cz/clanky/programovaci-jazyk-clojure-zaklady-zpracovani-xml/
  20. Programovací jazyk Clojure – testování s využitím knihovny Expectations
    http://www.root.cz/clanky/programovaci-jazyk-clojure-testovani-s-vyuzitim-knihovny-expectations/
  21. Programovací jazyk Clojure – některé užitečné triky použitelné (nejenom) v testech
    http://www.root.cz/clanky/programovaci-jazyk-clojure-nektere-uzitecne-triky-pouzitelne-nejenom-v-testech/
  22. Enlive – výkonný šablonovací systém pro jazyk Clojure
    http://www.root.cz/clanky/enlive-vykonny-sablonovaci-system-pro-jazyk-clojure/
  23. Nástroj Leiningen a programovací jazyk Clojure: tvorba vlastních knihoven pro veřejný repositář Clojars
    http://www.root.cz/clanky/nastroj-leiningen-a-programovaci-jazyk-clojure-tvorba-vlastnich-knihoven-pro-verejny-repositar-clojars/
  24. Novinky v Clojure verze 1.8.0
    http://www.root.cz/clanky/novinky-v-clojure-verze-1–8–0/
  25. Asynchronní programování v Clojure s využitím knihovny core.async
    http://www.root.cz/clanky/asynchronni-programovani-v-clojure-s-vyuzitim-knihovny-core-async/
  26. Asynchronní programování v Clojure s využitím knihovny core.async (pokračování)
    http://www.root.cz/clanky/asynchronni-programovani-v-clojure-s-vyuzitim-knihovny-core-async-pokracovani/
  27. Asynchronní programování v Clojure s využitím knihovny core.async (dokončení)
    http://www.root.cz/clanky/asynchronni-programovani-v-clojure-s-vyuzitim-knihovny-core-async-dokonceni/
  28. Vytváříme IRC bota v programovacím jazyce Clojure
    http://www.root.cz/clanky/vytvarime-irc-bota-v-programovacim-jazyce-clojure/
  29. Gorilla REPL: interaktivní prostředí pro programovací jazyk Clojure
    https://www.root.cz/clanky/gorilla-repl-interaktivni-prostredi-pro-programovaci-jazyk-clojure/
  30. Multimetody v Clojure aneb polymorfismus bez použití OOP
    https://www.root.cz/clanky/multimetody-v-clojure-aneb-polymorfismus-bez-pouziti-oop/
  31. Práce s externími Java archivy v programovacím jazyku Clojure
    https://www.root.cz/clanky/prace-s-externimi-java-archivy-v-programovacim-jazyku-clojure/
  32. Clojure 16: Složitější uživatelská makra
    http://www.root.cz/clanky/programovaci-jazyk-clojure-16-slozitejsi-uzivatelska-makra/
  33. Clojure 17: Využití standardních maker v praxi
    http://www.root.cz/clanky/programovaci-jazyk-clojure-17-vyuziti-standardnich-maker-v-praxi/
  34. Clojure 18: Základní techniky optimalizace aplikací
    http://www.root.cz/clanky/programovaci-jazyk-clojure-18-zakladni-techniky-optimalizace-aplikaci/
  35. Clojure 19: Vývojová prostředí pro Clojure
    http://www.root.cz/clanky/programovaci-jazyk-clojure-19-vyvojova-prostredi-pro-clojure/
  36. Clojure 20: Vývojová prostředí pro Clojure (Vimu s REPL)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-20-vyvojova-prostredi-pro-clojure-integrace-vimu-s-repl/
  37. Clojure 21: ClojureScript aneb překlad Clojure do JS
    http://www.root.cz/clanky/programovaci-jazyk-clojure-21-clojurescript-aneb-preklad-clojure-do-javascriptu/
  38. Leiningen: nástroj pro správu projektů napsaných v Clojure
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure/
  39. Leiningen: nástroj pro správu projektů napsaných v Clojure (2)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-2/
  40. Leiningen: nástroj pro správu projektů napsaných v Clojure (3)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-3/
  41. Leiningen: nástroj pro správu projektů napsaných v Clojure (4)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-4/
  42. Leiningen: nástroj pro správu projektů napsaných v Clojure (5)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-5/
  43. Leiningen: nástroj pro správu projektů napsaných v Clojure (6)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-6/
  44. Programovací jazyk Clojure a databáze (1.část)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-databaze-1-cast/
  45. Pluginy pro Leiningen
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-pluginy-pro-leiningen/
  46. Programovací jazyk Clojure a knihovny pro práci s vektory a maticemi
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-knihovny-pro-praci-s-vektory-a-maticemi/
  47. Programovací jazyk Clojure a knihovny pro práci s vektory a maticemi (2)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-knihovny-pro-praci-s-vektory-a-maticemi-2/
  48. Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk
    http://www.root.cz/clanky/programovaci-jazyk-clojure-synteza-proceduralnich-textur-s-vyuzitim-knihovny-clisk/
  49. Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk (2)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-synteza-proceduralnich-textur-s-vyuzitim-knihovny-clisk-2/
  50. Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure
    http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure/
  51. Seesaw: knihovna pro snadnou tvorbu GUI v azyce Clojure (2)
    http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure-2/
  52. Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure (3)
    http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure-3/
  53. Programovací jazyk Clojure a práce s Gitem
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-prace-s-gitem/
  54. Programovací jazyk Clojure a práce s Gitem (2)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-prace-s-gitem-2/
  55. Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk (dokončení)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-synteza-proceduralnich-textur-s-vyuzitim-knihovny-clisk-dokonceni/
  56. Pixie: lehký skriptovací jazyk s „kouzelnými“ schopnostmi
    https://www.root.cz/clanky/pixie-lehky-skriptovaci-jazyk-s-kouzelnymi-schopnostmi/
  57. 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/
  58. Novinky v Clojure verze 1.9.0
    https://www.root.cz/clanky/novinky-v-clojure-verze-1–9–0/
  59. Validace dat s využitím knihovny spec v Clojure 1.9.0
    https://www.root.cz/clanky/validace-dat-s-vyuzitim-knihovny-spec-v-clojure-1–9–0/
  60. Použití jazyka Gherkin při tvorbě testovacích scénářů pro aplikace psané v Clojure
    https://www.root.cz/clanky/pouziti-jazyka-gherkin-pri-tvorbe-testovacich-scenaru-pro-aplikace-psane-v-nbsp-clojure/
  61. Použití jazyka Gherkin při tvorbě testovacích scénářů pro aplikace psané v Clojure (2)
    https://www.root.cz/clanky/pouziti-jazyka-gherkin-pri-tvorbe-testovacich-scenaru-pro-aplikace-psane-v-nbsp-clojure-2/
  62. Incanter: prostředí pro statistické výpočty s grafickým výstupem založené na Clojure
    https://www.root.cz/clanky/incanter-prostredi-pro-statisticke-vypocty-s-grafickym-vystupem-zalozene-na-clojure/
  63. Incanter: operace s maticemi
    https://www.root.cz/clanky/incanter-operace-s-maticemi/
  64. Interpret programovacího jazyka Clojure integrovaný do Jupyter Notebooku
    https://www.root.cz/clanky/interpret-programovaciho-jazyka-clojure-integrovany-do-jupyter-notebooku/
  65. Babashka: interpret Clojure určený pro rychlé spouštění utilit z příkazového řádku
    https://www.root.cz/clanky/babashka-interpret-clojure-urceny-pro-rychle-spousteni-utilit-z-prikazoveho-radku/
  66. Pokročilý streaming založený na Apache Kafce, jazyku Clojure a knihovně Jackdaw
    https://www.root.cz/clanky/pokrocily-streaming-zalozeny-na-apache-kafce-jazyku-clojure-a-knihovne-jackdaw/
  67. Pokročilý streaming založený na Apache Kafce, jazyku Clojure a knihovně Jackdaw (2. část)
    https://www.root.cz/clanky/pokrocily-streaming-zalozeny-na-apache-kafce-jazyku-clojure-a-knihovne-jackdaw-2-cast/
  68. Pokročilý streaming založený na projektu Apache Kafka, jazyku Clojure a knihovně Jackdaw (streamy a kolony)
    https://www.root.cz/clanky/pokrocily-streaming-zalozeny-na-projektu-apache-kafka-jazyku-clojure-a-knihovne-jackdaw-streamy-a-kolony/
  69. Řídicí struktury využitelné v programovacím jazyku Clojure
    https://www.root.cz/clanky/ridici-struktury-vyuzitelne-v-programovacim-jazyku-clojure/

19. Literatura

O Common Lispu, Scheme či Clojure, tedy o třech (s velkou pravděpodobností) nejpoužívanějších dialektech LISPu, vyšlo poměrně velké množství literatury. Pro Common Lisp je typická jeho velká stabilita, a to minimálně od roku 1994, což mj. znamená, že i původní vydaní prvních dvou dále zmíněných knih je zcela bez problémů použitelné i dnes (a obě knihy jsou navíc dobře čitelné):

  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, Barbara Kaiser, Karl Knight
    „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 adrese 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
  24. Graham Hutton
    A tutorial on the universality andexpressiveness of fold
    http://www.cs.nott.ac.uk/~pszgmh/fol­d.pdf

20. Odkazy na Internetu

  1. Hy 1.0.0: dialekt Lispu integrovaný do Pythonu
    https://www.root.cz/zpravicky/hy-1–0–0-dialekt-lispu-integrovany-do-pythonu/
  2. Janet Language
    https://janet-lang.org/
  3. Janet na GitHubu
    https://github.com/janet-lang/janet
  4. Janet for Mortals (a real book)
    https://janet.guide/
  5. Bauble studio
    https://bauble.studio/
  6. Janet na Hacker News
    https://news.ycombinator.com/i­tem?id=34843306
  7. Common Lisp
    https://lisp-lang.org/
  8. Why You Should Learn Lisp In 2022?
    https://www.youtube.com/wat­ch?v=GWdf1flcLoM
  9. LOOP Common Lisps Superior For
    https://www.youtube.com/wat­ch?v=i4tmF_1nZng
  10. Lisp VS C benchmarks
    https://programming-language-benchmarks.vercel.app/lisp-vs-c
  11. Common Lisp: An elegant design pattern
    https://www.youtube.com/wat­ch?v=9597LFlvMuE
  12. Common Lisp Macros By Example Tutorial
    https://lisp-journey.gitlab.io/blog/common-lisp-macros-by-example-tutorial/
  13. The Common Lisp Cookbook
    https://lispcookbook.github.io/cl-cookbook/
  14. The Evolution of Lisp
    https://www.csee.umbc.edu/cou­rses/331/resources/papers/E­volution-of-Lisp.pdf
  15. Awesome CL
    https://github.com/CodyRe­ichert/awesome-cl
  16. LISP
    https://taoofmac.com/space/dev/lisp
  17. Repositář projektu femtolisp
    https://github.com/JeffBe­zanson/femtolisp
  18. Femtolisp – lightweight, robust lisp interpreter built on reusable C libraries
    https://www.findbestopensou­rce.com/product/femtolisp
  19. YCombinator: Femtolisp: A lightweight, robust, scheme-like Lisp implementation
    https://news.ycombinator.com/i­tem?id=22094722
  20. Learning Julia by Anshul Joshi, Rahul Lakhanpal: Femtolisp
    https://www.oreilly.com/li­brary/view/learning-julia/9781785883279/2e85442f-d100–4b53-b8f7–7d20d62f0255.xhtml
  21. The role of femtolisp in Julia?
    https://discourse.julialang.org/t/the-role-of-femtolisp-in-julia/1902
  22. LispSyntax.jl: A clojure-like lisp syntax for julia
    https://github.com/swadey/Lis­pSyntax.jl
  23. What exactly code lowering is an how to do “unlowering”?
    https://discourse.julialang.org/t/what-exactly-code-lowering-is-an-how-to-do-unlowering/1315
  24. Interlisp.org: Dedicated to Restoring and Preserving the Interlisp experience
    https://github.com/Interlisp
  25. Warren Teitelman
    https://en.wikipedia.org/wi­ki/Warren_Teitelman
  26. InterLISP/65
    http://www.atarimania.com/utility-atari-400–800-xl-xe-interlisp-65_12477.html
  27. Lisp Editing in the 80s – Interlisp SEdit (Video)
    https://www.youtube.com/wat­ch?v=2qsmF8HHskg
  28. Inter-LISP
    http://www.atarimania.com/utility-atari-400–800-xl-xe-inter-lisp_29354.html
  29. InterLISP 65 Editing (video)
    https://www.youtube.com/wat­ch?v=nY_hcazo86A
  30. Datasoft INTER-LISP/65 (Atari Age, chat)
    https://atariage.com/forum­s/topic/116093-datasoft-inter-lisp65/
  31. Marvin Minsky – The beauty of the Lisp language (44/151)
    https://www.youtube.com/wat­ch?v=YaWVHyIBVeI
  32. History of LISP (Interlisp)
    http://www.softwarepreser­vation.org/projects/LISP/in­dex.html#INTERLISP_
  33. Computer-Assisted Instruction (Bits and Bytes, Episode 7)
    https://www.youtube.com/wat­ch?v=eURtTV_qKw8
  34. Můžeme věřit překladačům? Projekty řešící schéma „důvěřivé důvěry“
    https://www.root.cz/clanky/muzeme-verit-prekladacum-projekty-resici-schema-duverive-duvery/
  35. Gambit in the browser
    https://feeley.github.io/gambit-in-the-browser/
  36. A Tour of Scheme in Gambit
    http://dynamo.iro.umontre­al.ca/wiki/images/a/a7/A_Tou­r_of_Scheme_in_Gambit.pdf
  37. Gambit Scheme: Inside Out
    http://www.iro.umontreal.ca/~gam­bit/Gambit-inside-out.pdf
  38. Gambit Internal Documentation
    http://dynamo.iro.umontre­al.ca/wiki/index.php/Inter­nal_Documentation
  39. clojure-scheme: Compiling to Native Code via Scheme
    http://www.iro.umontreal.ca/~gam­bit/Sorenson-Clojure-to-Native-via-Scheme.pdf
  40. Gauche – a Scheme implementation
    http://practical-scheme.net/gauche/
  41. Scheme48
    https://s48.org/
  42. SISC (Second Interpreter of Scheme)
    http://sisc-scheme.org/
  43. The SCM Implementation of Scheme
    https://people.csail.mit.e­du/jaffer/SCM.html
  44. Ypsilon – The ultimate script language system for the video pinball fourth generation
    http://www.littlewingpinba­ll.com/doc/en/ypsilon/index­.html
  45. Chicken Scheme
    https://call-cc.org/
  46. Eggs Unlimited
    http://wiki.call-cc.org/chicken-projects/egg-index-5.html
  47. Chicken Scheme Wiki
    https://wiki.call-cc.org/
  48. CHICKEN for Python programmers
    https://wiki.call-cc.org/chicken-for-python-programmers
  49. Programming for Performance
    http://wiki.call-cc.org/programming-for-performance
  50. Using the compiler
    https://wiki.call-cc.org/man/4/Using%20the%20compiler
  51. CHICKEN Scheme tutorials
    https://wiki.call-cc.org/tutorials
  52. Racket: programovací jazyk a současně i platforma pro vývoj nových jazyků
    https://www.root.cz/clanky/racket-programovaci-jazyk-a-soucasne-i-platforma-pro-vyvoj-novych-jazyku/
  53. Makra v Racketu i v dalších lispovských jazycích
    https://www.root.cz/clanky/makra-v-racketu-i-v-dalsich-lispovskych-jazycich/
  54. Základní knihovna jazyka Racket
    https://www.root.cz/clanky/zakladni-knihovna-jazyka-racket/
  55. Grafický metaformát PostScript
    https://www.root.cz/clanky/graficky-metaformat-postscript/
  56. Vektorový grafický formát SVG
    https://www.root.cz/clanky/vektorovy-graficky-format-svg/
  57. The Racket Drawing Toolkit
    https://docs.racket-lang.org/draw/index.html
  58. Traditional Turtles
    https://docs.racket-lang.org/turtles/Traditio­nal_Turtles.html
  59. [racket] How best to repeat a function call n times?
    https://lists.racket-lang.org/users/archive/2014-September/064203.html
  60. Racket: Macros
    https://www.it.uu.se/edu/cou­rse/homepage/avfunpro/ht13/lec­tures/Racket-3-Macros.pdf
  61. Beautiful Racket / explainers: Macros
    https://beautifulracket.com/ex­plainer/macros.html
  62. Macros (dokumentace k Racketu)
    https://docs.racket-lang.org/guide/macros.html
  63. Model syntaxe jazyka Racket
    https://docs.racket-lang.org/reference/syntax-model.html
  64. Syntax Objects
    https://docs.racket-lang.org/guide/stx-obj.html
  65. Tech behind Tech: Clojure Macros Simplified
    http://techbehindtech.com/2010/09/28/clo­jure-macros-simplified/
  66. Fatvat – Exploring functional programming: Clojure Macros
    http://www.fatvat.co.uk/2009/02/clo­jure-macros.html
  67. Beautiful Racket: an introduction to language-oriented programming using Racket
    https://beautifulracket.com/
  68. Stránky projektu Racket
    https://racket-lang.org/
  69. Dokumentace k projektu Racket
    https://docs.racket-lang.org/index.html
  70. Seznam dostupných balíčků pro Racket
    https://pkgs.racket-lang.org/
  71. Racket na Wikipedii
    https://en.wikipedia.org/wi­ki/Racket_(programming_lan­guage)
  72. Vector Library (R7RS-compatible)
    https://srfi.schemers.org/srfi-133/srfi-133.html
  73. Blogy o Racketu a navazujících technologiích
    https://blog.racket-lang.org/
  74. Prográmky psané v Racketu na RosettaCode
    http://rosettacode.org/wi­ki/Category:Racket
  75. Fear of Macros
    https://www.greghendershott.com/fear-of-macros/
  76. Rackjure
    https://github.com/greghen­dershott/rackjure
  77. Matthew Flatt’s proposal to change Racket’s s-expressions based syntax to infix representation creates a stir in the community
    https://hub.packtpub.com/matthew-flatts-proposal-to-change-rackets-s-expressions-based-syntax-to-infix-representation-creates-a-stir-in-the-community/
  78. Racket News
    https://racket-news.com/
  79. Racket: Lisp for learning
    https://lwn.net/Articles/795385/
  80. Future of Racket
    https://www.greghendershot­t.com/2019/07/future-of-racket.html
  81. Vectors (pro Gauche)
    https://practical-scheme.net/gauche/man/gauche-refe/Vectors.html
  82. Kawa: Compiling Scheme to Java
    https://www.mit.edu/afs.new/sip­b/project/kawa/doc/kawa-tour.html
  83. Kawa in Languages shootout
    http://per.bothner.com/blog/2010/Kawa-in-shootout/
  84. Kawa 2.0 Supports Scheme R7RS
    https://developers.slashdot­.org/story/14/12/13/2259225/ka­wa-20-supports-scheme-r7rs/
  85. Kawa — fast scripting on the Java platform
    https://lwn.net/Articles/623349/
  86. Tail call (a její optimalizace)
    https://en.wikipedia.org/wi­ki/Tail_call
  87. SLIME (Wikipedia)
    http://en.wikipedia.org/wiki/SLIME
  88. slime.vim
    http://s3.amazonaws.com/mps/slime.vim
  89. What are the best scheme implementations?
    https://www.slant.co/topic­s/5282/~scheme-implementations
  90. Bigloo homepage
    http://www-sop.inria.fr/mimosa/fp/Bigloo/
  91. FTP s tarbally Bigloo
    ftp://ftp-sop.inria.fr/indes/fp/Bigloo
  92. GOTO 2018 • Functional Programming in 40 Minutes • Russ Olsen
    https://www.youtube.com/wat­ch?v=0if71HOyVjY
  93. TinyScheme (stránka na Sourceforge)
    http://tinyscheme.sourcefor­ge.net/home.html
  94. Embedding Tiny Scheme in a Game
    http://www.silicondelight­.com/embedding-tiny-scheme-in-a-game/
  95. Embedding Scheme for a game mission scripting DSL
    http://carloscarrasco.com/embedding-scheme-for-a-game-mission-scripting-dsl.html
  96. Všechny verze TinyScheme na SourceForge
    https://sourceforge.net/pro­jects/tinyscheme/files/ti­nyscheme/
  97. Fork TinyScheme na GitHubu
    https://github.com/yawnt/tinyscheme
  98. Ackermannova funkce
    https://cs.wikipedia.org/wi­ki/Ackermannova_funkce
  99. Ackermann function na Rosetta Code
    https://rosettacode.org/wi­ki/Ackermann_function#Sche­me
  100. Success Stories (lisp.org)
    https://lisp-lang.org/success/
  101. Allegro Common Lisp Success Stories
    https://franz.com/success/
  102. Clojure Success Stories
    https://clojure.org/commu­nity/success_stories
  103. Scheme Quick Reference
    https://www.st.cs.uni-saarland.de/edu/config-ss04/scheme-quickref.pdf
  104. Slajdy o Scheme (od slajdu číslo 15)
    https://docs.google.com/pre­sentation/d/1abmDnKjrq1tcjGvvRNAK­hOiSTSE2lyagtcEPal07Gbo/e­dit
  105. Scheme Cheat Sheet
    https://github.com/smythp/scheme-cheat-sheet
  106. Embedding Lua, embedding Guile
    http://puntoblogspot.blog­spot.com/2013/04/embedding-lua-embedding-guile.html
  107. Lambda Papers
    https://en.wikisource.org/wi­ki/Lambda_Papers
  108. Revised7Report on the Algorithmic Language Scheme
    https://small.r7rs.org/at­tachment/r7rs.pdf
  109. Video Lectures (MIT, SICP 2005)
    https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6–001-structure-and-interpretation-of-computer-programs-spring-2005/video-lectures/
  110. Why is Scheme my first language in university?
    https://softwareengineerin­g.stackexchange.com/questi­ons/115252/why-is-scheme-my-first-language-in-university
  111. The Perils of JavaSchools
    https://www.joelonsoftware­.com/2005/12/29/the-perils-of-javaschools-2/
  112. How to Design Programs, Second Edition
    https://htdp.org/2019–02–24/index.html
  113. LilyPond
    http://lilypond.org/
  114. LilyPond — Extending (přes Scheme)
    http://lilypond.org/doc/v2­.18/Documentation/extendin­g/scheme-tutorial
  115. Scheme in LilyPond
    http://lilypond.org/doc/v2­.18/Documentation/extendin­g/scheme-in-lilypond
  116. GnuCash
    http://www.gnucash.org/
  117. Custom Reports (in GNU Cash)
    https://wiki.gnucash.org/wi­ki/Custom_Reports
  118. Program by Design
    https://programbydesign.org/
  119. SchemePy
    https://pypi.org/project/SchemePy/
  120. LISP FQA: Section – [1–5] What is the „minimal“ set of primitives needed for a Lisp interpreter?
    http://www.faqs.org/faqs/lisp-faq/part1/section-6.html
  121. femtolisp
    https://github.com/JeffBe­zanson/femtolisp
  122. (How to Write a (Lisp) Interpreter (in Python))
    http://norvig.com/lispy.html
  123. Repositář s Guile Emacsem
    http://git.hcoop.net/?p=bpt/guile.git
  124. Interacting with Guile Compound Data Types in C
    http://www.lonelycactus.com/gu­ilebook/x1555.html
  125. Calling Guile functions from C
    http://www.lonelycactus.com/gu­ilebook/c1204.html#SECCAL­LGUILEFUNC
  126. Arrays, and other compound data types
    http://www.lonelycactus.com/gu­ilebook/charrays.html
  127. Interacting with Guile Compound Data Types in C
    http://www.lonelycactus.com/gu­ilebook/x1555.html
  128. Guile Reference Manual
    https://www.gnu.org/softwa­re/guile/manual/html_node/in­dex.html
  129. Scheme: Summary of Common Syntax
    https://www.gnu.org/softwa­re/guile/manual/html_node/Syn­tax-Summary.html#Syntax-Summary
  130. Scripting with Guile: Extension language enhances C and Scheme
    https://www.ibm.com/develo­perworks/library/l-guile/index.html
  131. Having fun with Guile: a tutorial
    http://dustycloud.org/misc/guile-tutorial.html
  132. Guile: Loading Readline Support
    https://www.gnu.org/softwa­re/guile/manual/html_node/Lo­ading-Readline-Support.html#Loading-Readline-Support
  133. lispy
    https://pypi.org/project/lispy/
  134. Lython
    https://pypi.org/project/Lython/
  135. Lizpop
    https://pypi.org/project/lizpop/
  136. Budoucnost programovacích jazyků
    http://www.knesl.com/budoucnost-programovacich-jazyku
  137. LISP Prolog and Evolution
    http://blog.samibadawi.com/2013/05/lisp-prolog-and-evolution.html
  138. List of Lisp-family programming languages
    https://en.wikipedia.org/wi­ki/List_of_Lisp-family_programming_languages
  139. clojure_py na indexu PyPi
    https://pypi.python.org/py­pi/clojure_py
  140. PyClojure
    https://github.com/eigenhom­bre/PyClojure
  141. Hy na GitHubu
    https://github.com/hylang/hy
  142. Hy: The survival guide
    https://notes.pault.ag/hy-survival-guide/
  143. Hy běžící na monitoru terminálu společnosti Symbolics
    http://try-hy.appspot.com/
  144. Welcome to Hy’s documentation!
    http://docs.hylang.org/en/stable/
  145. Hy na PyPi
    https://pypi.org/project/hy/#des­cription
  146. Getting Hy on Python
    https://lwn.net/Articles/596626/
  147. Programming Can Be Fun with Hy
    https://opensourceforu.com/2014/02/pro­gramming-can-fun-hy/
  148. Přednáška o projektu Hy (pětiminutový lighttalk)
    http://blog.pault.ag/day/2013/04/02
  149. Hy (Wikipedia)
    https://en.wikipedia.org/wiki/Hy
  150. GNU Emacs Lisp Reference Manual: Point
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Point.html
  151. GNU Emacs Lisp Reference Manual: Narrowing
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Narrowing.html
  152. GNU Emacs Lisp Reference Manual: Functions that Create Markers
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Creating-Markers.html
  153. GNU Emacs Lisp Reference Manual: Motion
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Motion.html#Motion
  154. GNU Emacs Lisp Reference Manual: Basic Char Syntax
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­lisp/Basic-Char-Syntax.html
  155. Elisp: Sequence: List, Array
    http://ergoemacs.org/emac­s/elisp_list_vs_vector.html
  156. Elisp: Property List
    http://ergoemacs.org/emac­s/elisp_property_list.html
  157. Elisp: Hash Table
    http://ergoemacs.org/emac­s/elisp_hash_table.html
  158. Elisp: Association List
    http://ergoemacs.org/emac­s/elisp_association_list.html
  159. The mapcar Function (An Introduction to Programming in Emacs Lisp)
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­intr/mapcar.html
  160. Anaphoric macro
    https://en.wikipedia.org/wi­ki/Anaphoric_macro
  161. Some Common Lisp Loop Macro Examples
    https://www.youtube.com/wat­ch?v=3yl8o6r_omw
  162. A Guided Tour of Emacs
    https://www.gnu.org/softwa­re/emacs/tour/
  163. The Roots of Lisp
    http://www.paulgraham.com/ro­otsoflisp.html
  164. Evil (Emacs Wiki)
    https://www.emacswiki.org/emacs/Evil
  165. Evil (na GitHubu)
    https://github.com/emacs-evil/evil
  166. Evil (na stránkách repositáře MELPA)
    https://melpa.org/#/evil
  167. 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
  168. GNU Emacs (home page)
    https://www.gnu.org/software/emacs/
  169. GNU Emacs (texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?GnuEmacs
  170. An Introduction To Using GDB Under Emacs
    http://tedlab.mit.edu/~dr/gdbin­tro.html
  171. An Introduction to Programming in Emacs Lisp
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­intr/index.html
  172. 27.6 Running Debuggers Under Emacs
    https://www.gnu.org/softwa­re/emacs/manual/html_node/e­macs/Debuggers.html
  173. GdbMode
    http://www.emacswiki.org/e­macs/GdbMode
  174. Emacs (Wikipedia)
    https://en.wikipedia.org/wiki/Emacs
  175. Emacs timeline
    http://www.jwz.org/doc/emacs-timeline.html
  176. Emacs Text Editors Family
    http://texteditors.org/cgi-bin/wiki.pl?EmacsFamily
  177. Vrapper aneb spojení možností Vimu a Eclipse
    https://mojefedora.cz/vrapper-aneb-spojeni-moznosti-vimu-a-eclipse/
  178. 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/
  179. Emacs/Evil-mode – A basic reference to using evil mode in Emacs
    http://www.aakarshnair.com/posts/emacs-evil-mode-cheatsheet
  180. From Vim to Emacs+Evil chaotic migration guide
    https://juanjoalvarez.net/es/de­tail/2014/sep/19/vim-emacsevil-chaotic-migration-guide/
  181. Introduction to evil-mode {video)
    https://www.youtube.com/wat­ch?v=PeVQwYUxYEg
  182. EINE (Emacs Wiki)
    http://www.emacswiki.org/emacs/EINE
  183. EINE (Texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?EINE
  184. ZWEI (Emacs Wiki)
    http://www.emacswiki.org/emacs/ZWEI
  185. ZWEI (Texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?ZWEI
  186. Zmacs (Wikipedia)
    https://en.wikipedia.org/wiki/Zmacs
  187. Zmacs (Texteditors.org)
    http://texteditors.org/cgi-bin/wiki.pl?Zmacs
  188. TecoEmacs (Emacs Wiki)
    http://www.emacswiki.org/e­macs/TecoEmacs
  189. Micro Emacs
    http://www.emacswiki.org/e­macs/MicroEmacs
  190. Micro Emacs (Wikipedia)
    https://en.wikipedia.org/wi­ki/MicroEMACS
  191. EmacsHistory
    http://www.emacswiki.org/e­macs/EmacsHistory
  192. Seznam editorů s ovládáním podobným Emacsu či kompatibilních s příkazy Emacsu
    http://www.finseth.com/emacs.html
  193. evil-numbers
    https://github.com/cofi/evil-numbers
  194. Debuggery a jejich nadstavby v Linuxu (1.část)
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu/
  195. Debuggery a jejich nadstavby v Linuxu (2.část)
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-2-cast/
  196. Debuggery a jejich nadstavby v Linuxu (3): Nemiver
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-3-nemiver/
  197. Debuggery a jejich nadstavby v Linuxu (4): KDbg
    http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-4-kdbg/
  198. 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/
  199. Org mode
    https://orgmode.org/
  200. The Org Manual
    https://orgmode.org/manual/index.html
  201. Kakoune (modální textový editor)
    http://kakoune.org/
  202. Vim-style keybinding in Emacs/Evil-mode
    https://gist.github.com/tro­yp/6b4c9e1c8670200c04c16036805773d8
  203. Emacs – jak začít
    http://www.abclinuxu.cz/clan­ky/navody/emacs-jak-zacit
  204. Programovací jazyk LISP a LISP machines
    https://www.root.cz/clanky/pro­gramovaci-jazyk-lisp-a-lisp-machines/
  205. Evil-surround
    https://github.com/emacs-evil/evil-surround
  206. Spacemacs
    http://spacemacs.org/
  207. Lisp: Common Lisp, Racket, Clojure, Emacs Lisp
    http://hyperpolyglot.org/lisp
  208. Common Lisp, Scheme, Clojure, And Elisp Compared
    http://irreal.org/blog/?p=725
  209. Does Elisp Suck?
    http://irreal.org/blog/?p=675
  210. Emacs pro mírně pokročilé (9): Elisp
    https://www.root.cz/clanky/emacs-elisp/
  211. 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/
  212. Clojure(Script) Interactive Development Environment that Rocks!
    https://github.com/clojure-emacs/cider
  213. An Introduction to Emacs Lisp
    https://harryrschwartz.com/2014/04/08/an-introduction-to-emacs-lisp.html
  214. Emergency Elisp
    http://steve-yegge.blogspot.com/2008/01/emergency-elisp.html
  215. Lambda calculus
    https://en.wikipedia.org/wi­ki/Lambda_calculus
  216. 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/
  217. Micro Manual LISP
    https://www.scribd.com/do­cument/54050141/Micro-Manual-LISP
  218. How Lisp Became God's Own Programming Language
    https://twobithistory.org/2018/10/14/lis­p.html
  219. History of Lisp
    http://jmc.stanford.edu/ar­ticles/lisp/lisp.pdf
  220. The Roots of Lisp
    http://languagelog.ldc.upen­n.edu/myl/llog/jmc.pdf
  221. Racket
    https://racket-lang.org/
  222. The Racket Manifesto
    http://felleisen.org/matthi­as/manifesto/
  223. MIT replaces Scheme with Python
    https://www.johndcook.com/blog/2009/03/26/mit-replaces-scheme-with-python/
  224. Adventures in Advanced Symbolic Programming
    http://groups.csail.mit.e­du/mac/users/gjs/6.945/
  225. Why MIT Switched from Scheme to Python (2009)
    https://news.ycombinator.com/i­tem?id=14167453
  226. Starodávná stránka XLispu
    http://www.xlisp.org/
  227. AutoLISP
    https://en.wikipedia.org/wi­ki/AutoLISP
  228. Seriál PicoLisp: minimalistický a výkonný interpret Lispu
    https://www.root.cz/serialy/picolisp-minimalisticky-a-vykonny-interpret-lispu/
  229. Common Lisp
    https://common-lisp.net/
  230. Getting Going with Common Lisp
    https://cliki.net/Getting%20Started
  231. Online Tutorial (Common Lisp)
    https://cliki.net/online%20tutorial
  232. Guile Emacs
    https://www.emacswiki.org/e­macs/GuileEmacs
  233. Guile Emacs History
    https://www.emacswiki.org/e­macs/GuileEmacsHistory
  234. Guile is a programming language
    https://www.gnu.org/software/guile/
  235. MIT Scheme
    http://groups.csail.mit.e­du/mac/projects/scheme/
  236. SIOD: Scheme in One Defun
    http://people.delphiforum­s.com/gjc//siod.html
  237. CommonLispForEmacs
    https://www.emacswiki.org/e­macs/CommonLispForEmacs
  238. Elisp: print, princ, prin1, format, message
    http://ergoemacs.org/emac­s/elisp_printing.html
  239. Special Forms in Lisp
    http://www.nhplace.com/ken­t/Papers/Special-Forms.html
  240. Basic Building Blocks in LISP
    https://www.tutorialspoin­t.com/lisp/lisp_basic_syn­tax.htm
  241. Introduction to LISP – University of Pittsburgh
    https://people.cs.pitt.edu/~mi­los/courses/cs2740/Lectures/Lis­pTutorial.pdf
  242. Why don't people use LISP
    https://forums.freebsd.org/threads/why-dont-people-use-lisp.24572/
  243. Structured program theorem
    https://en.wikipedia.org/wi­ki/Structured_program_the­orem
  244. Clojure: API Documentation
    https://clojure.org/api/api
  245. Tutorial for the Common Lisp Loop Macro
    http://www.ai.sri.com/pkarp/loop.html
  246. Common Lisp's Loop Macro Examples for Beginners
    http://www.unixuser.org/~e­uske/doc/cl/loop.html
  247. A modern list api for Emacs. No 'cl required.
    https://github.com/magnars/dash.el
  248. The LOOP Facility
    http://www.lispworks.com/do­cumentation/HyperSpec/Body/06_a­.htm
  249. Clojure.org: Vars and the Global Environment
    http://clojure.org/Vars
  250. Clojure.org: Refs and Transactions
    http://clojure.org/Refs
  251. Clojure.org: Atoms
    http://clojure.org/Atoms
  252. Clojure.org: Agents as Asynchronous Actions
    http://clojure.org/agents
  253. Transient Data Structureshttp://clojure.or­g/transients
  254. Dynamic Languages Strike Back
    http://steve-yegge.blogspot.cz/2008/05/dynamic-languages-strike-back.html
  255. Scripting: Higher Level Programming for the 21st Century
    http://www.tcl.tk/doc/scripting.html
  256. Clojure (na Wikipedia EN)
    http://en.wikipedia.org/wiki/Clojure
  257. Clojure (na Wikipedia CS)
    http://cs.wikipedia.org/wiki/Clojure
  258. SICP (The Structure and Interpretation of Computer Programs)
    http://mitpress.mit.edu/sicp/
  259. Pure function
    http://en.wikipedia.org/wi­ki/Pure_function
  260. Funkcionální programování
    http://cs.wikipedia.org/wi­ki/Funkcionální_programová­ní
  261. 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/
  262. Pixie: lehký skriptovací jazyk s „kouzelnými“ schopnostmi
    https://www.root.cz/clanky/pixie-lehky-skriptovaci-jazyk-s-kouzelnymi-schopnostmi/
  263. 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/
  264. The Nature of Lisp
    https://defmacro.org/ramblin­gs/lisp.html
  265. Stránka projektu Jython
    http://www.jython.org/
  266. Jython (Wikipedia)
    https://en.wikipedia.org/wiki/Jython
  267. Scripting for the Java Platform (Wikipedia)
    https://en.wikipedia.org/wi­ki/Scripting_for_the_Java_Plat­form
  268. JSR 223: Scripting for the JavaTM Platform
    https://jcp.org/en/jsr/detail?id=223
  269. List of JVM languages
    https://en.wikipedia.org/wi­ki/List_of_JVM_languages
  270. The JavaTM Virtual Machine Specification, Second Edition
    http://java.sun.com/docs/bo­oks/jvms/second_edition/html/VMSpec­TOC.doc.html
  271. The class File Format
    http://java.sun.com/docs/bo­oks/jvms/second_edition/html/Clas­sFile.doc.html
  272. javap – The Java Class File Disassembler
    http://docs.oracle.com/ja­vase/1.4.2/docs/tooldocs/win­dows/javap.html
  273. javap-java-1.6.0-openjdk(1) – Linux man page
    http://linux.die.net/man/1/javap-java-1.6.0-openjdk
  274. Using javap
    http://www.idevelopment.in­fo/data/Programming/java/mis­cellaneous_java/Using_javap­.html
  275. Examine class files with the javap command
    http://www.techrepublic.com/ar­ticle/examine-class-files-with-the-javap-command/5815354
  276. Economy Size Geek – Interview with Rich Hickey, Creator of Clojure
    https://www.linuxjournal.com/ar­ticle/10708
  277. Pyrsistent: persistentní datové struktury v Pythonu
    https://www.root.cz/clanky/pyrsistent-persistentni-datove-struktury-v-pythonu/
  278. Pyrsistent: persistentní datové struktury v Pythonu (dokončení)
    https://www.root.cz/clanky/pyrsistent-persistentni-datove-struktury-v-pythonu-dokonceni/
Neutrální ikona do widgetu na odběr článků ze seriálů

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.


Autor článku

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