Obsah
1. Femtolisp: varianta LISPu tvořící součást jazyka Julia
2. Různé implementace programovacího jazyka Scheme
4. Femtolisp jako součást programovacího jazyky Julia
5. Překlad Femtolispu s bootstrapingem
6. Skutečně minimalistická implementace?
7. Vylepšení REPLu jazyka Femtolisp
8. Základní vlastnosti jazyka Femtolisp
10. Pojmenované funkce s proměnným počtem parametrů
11. Povinné a nepovinné parametry pojmenovaných funkcí
17. Repositář s demonstračními příklady
1. Femtolisp: varianta LISPu tvořící součást jazyka Julia
„Almost everybody has their own lisp implementation. Some programmers' dogs and cats probably have their own lisp implementations as well. This is great, but too often I see people omit some of the obscure but critical features that make lisp uniquely wonderful. These include read macros like #. and backreferences, gensyms, and properly escaped symbol names. If you're going to waste everybody's time with yet another lisp, at least do it right damnit.“
Jeff Bezanson, autor jazyka Femtolisp a spoluautor jazyka Julia
Na stránkách Roota jsme si – jak již ostatně bylo zmíněno v perexu dnešního článku – popsali relativně velké množství různých dialektů a implementací programovacích jazyků LISP a Scheme (viz též osmnáctou kapitolu s odkazy na jednotlivé články o tomto tématu). Jednotlivé implementace se od sebe odlišují jak poskytovanými možnostmi (některé dialekty například nepodporují tradiční LISPovské tečka-dvojice, další zase nemají plnohodnotné TCO), podporou či naopak nepodporou nějakého standardu (R5RS, R6RS, R7RS, ANSI CommonLISP), tak i použitými technologiemi. V prozatím popsaných projektech tedy můžeme najít jak klasické interpretry, tak i překladače, a to buď překladače do strojového kódu, překladače do bajtkódu (JVM, WebAssembly), použití just-in-time překladače atd. Jednotlivé implementace se od sebe odlišují taktéž použitým správcem paměti (garbage collector) – což je technologie, která do značné míry ovlivňuje úspěch či neúspěch implementace LISPu/Scheme v produkčním prostředí.

Obrázek 1: Na tomto grafu evoluce programovacích jazyků můžeme vidět některé historicky významné programovací jazyky, s nimiž jsme se již setkali v seriálu o historii počítačů. Jedná se zejména o Fortran, Cobol, SNOBOL, Algol, APL, BASIC (resp. přesněji řečeno celá rodina jazyků nesoucích toho jméno) a samozřejmě taktéž o LISP a jeho varianty.

Obrázek 2: Alonzo Church, autor slavného lambda kalkulu, na němž jsou nepřímo postaveny všechny LISPovské jazyky.
2. Různé implementace programovacího jazyka Scheme
V případě, že se zaměříme na projekty implementující nějaký standard jazyka Scheme (a reálně použitelných a nasaditelných implementací Scheme dnes existuje přibližně padesát!), můžeme tyto projekty rozdělit do několika skupin:
- V první skupině nalezneme klasické interpretry běžící nad nějakým virtuálním strojem popř. překladače do bajtkódu těchto virtuálních strojů. Do této kategorie patří například Gauche, již v úvodní kapitole zmíněný GNU Guile, systém Kawa, Scheme48, SISC (Second Interpreter of Scheme), SCM či Ypsilon (ten se používá pro programování pravidel pinballů, resp. video verzí těchto her). Některé ze zmíněných implementací Scheme používají vlastní virtuální stroj (Guile), další pak nějakou již existující variantu virtuálního stroje (Kawa, SISC). Z modernějších virtuálních strojů (resp. bajtkódů pro ně) je nutné zmínit WebAssembly. Existují minimálně dvě implementace Scheme pro WebAssembly – Schism a PollRobots scheme.
- Ve druhé skupině, která je relativně rozsáhlá, nalezneme překladače programovacího jazyka Scheme do nativního (strojového) kódu. Do této kategorie můžeme zařadit například Chez Scheme (ten získal nejlepší hostname pro svoji domácí stránku), Ikarus, Larceny, MIT Scheme, MzScheme či již popsaný rozsáhlý systém Racket založený na MzScheme, který je mj. používán i pro výuku (a to mj. i proto, že obsahuje vlastní GUI, podporu pro tvorbu grafů, interpretry dalších jazyků, mnohá rozšíření syntaxe založená na systému maker apod.).
- A konečně existuje i skupina implementací programovacího jazyka Scheme založená na transpřekladači (transcompileru, transpileru), typicky s výstupem do programovacího jazyka C. To znamená, že se vstupní kód napsaný v jazyce Scheme analyzuje, transformuje a optimalizuje, ovšem výstupem není přímo strojový kód, ale více či méně čitelný kód naprogramovaný v jazyku C (a teoreticky samozřejmě i do jiného jazyka, podle mě by byl v této roli ideální jazyk Rust). Do této skupiny řadíme především čtveřici Bigloo, Chicken, Gambit-C a Stalin. Do této skupiny patří i projekt Gambit a Loko Scheme (taktéž se zajímavou doménou). Ovšem transpřekladačem může být vybavena i implementace SISC zmíněná v první skupině (tento transpřekladač se jmenuje Hobbit).
Obrázek 3: Jedna z mnoha knih o jazyce Scheme.
3. Dialekty LISPu
„The default language, embodied in a succession of popular languages, has gradually evolved toward Lisp.“
Paul Graham
Ve světě programovacího jazyka LISP je situace chaotičtější a současně i zajímavější, než je tomu v případě Scheme (jehož varianty typicky podporují R5RS, R6RS a blíží se k R7RS). Jednotlivé implementace LISPu totiž nemusí striktně odpovídat nějakému standardu (tedy obdobě RnRS). Nepsaným standardem v této oblasti je sice Common Lisp (přesněji ANSI Common Lisp je standard, ovšem zbytečně nabobtnalý), ovšem jen několik dalších implementací LISPu se tomuto jazyku přibližuje. Neexistence všemi akceptovaného standardu vedla k tomu, že vzniklo mnoho alternativních dialektů LISPu popř. různých kombinací LISPu a Scheme (mimochodem: právě do této kategorie lze zařadit i dnes popisovaný Femtolisp). Příkladem odklonu od dosti rozsáhlého Common Lispu může být PicoLisp, což je interpret LISPu pojatý striktně minimalisticky – a ve své základní variantě odlišný od ostatních implementací LISPu. Zdrojové kódy PicoLispu přitom existují ve dvou variantách. Pro všechny 32bitové procesory (a pro architektury odlišné od x86_64, tedy i pro ARM atd.) se používá varianta naprogramovaná v programovacím jazyce C, pro 64bitové procesory řady x86_64 se pak používá varianta, v níž je část zdrojových kódů vytvořena v assembleru a je vůči céčkové variantě optimalizována (jak s ohledem na velikost, tak i rychlost interpretace).

Obrázek 4: Vývoj některých dialektů Lispu.
Zdroj: Wikipedia.
Samostatnou kapitolou je pak Interlisp, což původně byl dialekt LISPu, který zavedl některé nové zajímavé technologie a díky své historii je velmi zajímavý i v pohledu na vývoj celého IT. Interlisp (psaný původně verzálkami, tedy INTERLISP či InterLisp) se lišil od většiny tehdejších interpretrů. Původní Lispy totiž do značné míry vypadaly tak, jako například dnešní GNU Guile nebo dnes popisovaný Femtolisp – všechny formy musely být zapsány jako s-výrazy, přičemž se netolerovaly žádné chyby, závorky musely být balancovány atd. Interlisp byl v tomto ohledu dosti odlišný. Zejména byly rozšířeny možnosti nástrojů dodávaných společně s tímto jazykem – přidán byl například v té době přelomový korektor překlepů, přidány byly balíčky pro práci se soubory, balíček CLISP umožňující zápis algebraických výrazů, programátorský editor pro strukturovaný kód atd. Pro moderní platformy lze namísto původního Interlispu využít projekt nazvaný přímočaře LISPF4 – InterLisp Interpreter, který je možné nalézt na GitHubu, konkrétně na adrese https://github.com/blakemcbride/LISPF4. V rámci tohoto projektu došlo k přepsání těch částí Interlispu, které byly původně vytvořeny v assembleru (a to v assembleru pro dobové mainframy a minipočítače). Přepisem těchto obecně velmi těžko přenositelných částí do programovacího jazyka C se zajistila mnohem snadnější přenositelnost, takže dnes pro překlad stačí Linux se základními nástroji GNU toolchainu (překladač jazyka C, linker).

Obrázek 5: Úvodní obrazovka Interlispu/65, což je varianta Intelispu pro osmibitové mikroprocesory MOS 6502.
A nesmíme zapomenout ani na transpilery, mezi něž patří například jazyk Hy, jemuž jsme se na stránkách Roota taktéž věnovali. Programovací jazyk Hy je určen pro ekosystém jazyka Python. Programátorem zapsaný kód transformuje do Pythonu s využitím AST a dokonce dokáže zdrojový LISPovský kód transformovat do Pythonu a teprve poté ho spustit. To je výhodná vlastnost, protože umožňuje Hy integrovat například s existujícími debuggery atd. Překlad přes AST nebo Python podporuje jak Python 2.x, tak i Python 3.x. Další důležitou vlastností Hy je možnost plné kooperace mezi kódem zapsaným přímo v tomto jazyku a Pythoním kódem, což znamená, že je možné použít všechny Pythonovské knihovny a frameworky (včetně Numpy, PyTorch, Flask atd.) a naopak – například mít napsanou aplikaci v Pythonu a pro manipulaci se symboly použít Hy (v tomto ohledu jsou homoikonické programovací jazyky s makry podle mého názoru mnohem lepší než samotný Python, ostatně na tomto konceptu staví i jazyk Julia).

Obrázek 6: Hra Abuse je z velké části napsána v LISPu – nízkoúrovňové části používají nativní knihovny (na Linuxu například SDL), ovšem veškerá herní logika je skutečně v LISPu a s troškou vůle a volného času lze z Abuse vytvořit zcela odlišnou hru. Zdánlivá malá výkonnost LISPu se zde neprojevuje, protože Abuse lze bez problémů hrát i na stařičkém počítači s mikroprocesorem 80486DX2 (ostatně nízká výkonnost LISPu je pro mnoho jeho implementací spíše legendou, než faktem).

Obrázek 7: Specifikem Interlispu/65 je existence funkcí POKE, PEEK, STICK atd., tedy funkcí známých z Atari BASICu a důležitých pro vývoj reálných aplikací. Zde se s využitím funkce POKE změnil obsah barvového registru s barvou pozadí obrazovky v textovém režimu.
4. Femtolisp se představuje
„You mean, how much you can develop during a PhD on scientific computing with a known technical computing syntax and paradigm on top of a modular compiler infrastructure with an enthusiastic community?“
Dnes popisovaný dialekt jazyka LISP (resp. spíše Scheme, které je samo o sobě dialekt LISPu) se jmenuje Femtolisp. Za vývojem tohoto programovacího jazyka, jehož zdrojové kódy i (poněkud stručnou) dokumentaci najdete na https://github.com/JeffBezanson/femtolisp, stojí Jeff Bezanson, který je ovšem známější jako spoluautor programovacího jazyka Julia. Jeff se kromě dalších věcí z oblasti computer science zabývá i typovými systémy, viz též text jeho doktorské práce (ostatně i jemu můžeme vděčit za typový systém Julie). Femtolisp je sice relativně minimalistickou implementací LISPu/Scheme, ovšem obsahuje prakticky všechny důležité ikredience tohoto jazyka, a to včetně podpory TCO a makrosystému. Jednou z chybějících věcí je podpora pro „dlouhá“ celá čísla a pro zlomky, což Femtolisp odlišuje například od již popsaného projektu Guile.
Z praktického hlediska je důležité, že Femtolisp je dnes součástí již zmíněného jazyka Julia, protože je použit pro parsing zdrojových kódů. Ostatně právě poměrně pokročilý makrosystém jazyka Julia je umožněn tím, že je parsing naprogramován pravě ve Femtolispu, tedy v jazyku, v němž je manipulace se stromy (AST) snadná. V rámci zpracování zdrojových kódů se totiž provádí několik operací, mezi jinými i transformace podobná této:
f(a, b) = sum(a' * b + a * b') Main.sum(Main.+(Main.Ac_mul_B(a,b),Main.A_mul_Bc(a,b)))
Příklady využití Femtolispu naleznete přímo v repositáři jazyka Julia, například v souborech ast.scm a jlfrontend.scm.
O přítomnosti Femtolispu v jazyce Julia se můžeme snadno přesvědčit. Standardní REPL tohoto jazyka se spouští takto:
$ julia _ _ _(_)_ | Documentation: https://docs.julialang.org (_) | (_) (_) | _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help. | | | | | | |/ _` | | | | |_| | | | (_| | | Version 1.5.3 (2020-11-09) _/ |\__'_|_|_|\__'_| | Fedora 33 build |__/ |
Ovšem po zadání přepínače –lisp se spustí REPL jiného jazyka, konkrétně Femtolispu:
$ julia --lisp ; _ ; |_ _ _ |_ _ | . _ _ ; | (-||||_(_)|__|_)|_) ;-------------------|----------------------------------------------------------
5. Překlad Femtolispu s bootstrapingem
Získání funkční verze Femtolispu je snadné. Postačuje pouze použít základní vývojářské nástroje, konkrétně Git, Make a GNU C (popř. jiný překladač programovacího jazyka C). Nejprve je pochopitelně nutné získat zdrojové kódy:
$ git clone https://github.com/JeffBezanson/femtolisp.git Cloning into 'femtolisp'... remote: Enumerating objects: 2412, done. remote: Total 2412 (delta 0), reused 0 (delta 0), pack-reused 2412 Receiving objects: 100% (2412/2412), 1.60 MiB | 2.20 MiB/s, done. Resolving deltas: 100% (1498/1498), done.
Vlastní překlad je prováděn v několika fázích, protože je podporován takzvaný bootstraping. Nejdříve se přeloží jen ta nejzákladnější varianta jazyka a teprve poté všechny potřebné symboly a funkce:
$ cd femtolisp
$ make gcc -O2 -DNDEBUG -falign-functions -Wall -Wno-strict-aliasing -Illt -DUSE_COMPUTED_GOTO -c flisp.c -o flisp.o gcc -O2 -DNDEBUG -falign-functions -Wall -Wno-strict-aliasing -Illt -DUSE_COMPUTED_GOTO -c builtins.c -o builtins.o gcc -O2 -DNDEBUG -falign-functions -Wall -Wno-strict-aliasing -Illt -DUSE_COMPUTED_GOTO -c string.c -o string.o string.c: In function ‘fl_string_width’: string.c:56:21: warning: implicit declaration of function ‘wcwidth’ [-Wimplicit-function-declaration] 56 | int w = wcwidth(*(uint32_t*)cp_data(cp)); | ^~~~~~~ gcc -O2 -DNDEBUG -falign-functions -Wall -Wno-strict-aliasing -Illt -DUSE_COMPUTED_GOTO -c equalhash.c -o equalhash.o gcc -O2 -DNDEBUG -falign-functions -Wall -Wno-strict-aliasing -Illt -DUSE_COMPUTED_GOTO -c table.c -o table.o ... ... ... gcc -O3 -DNDEBUG -Wall -Wno-strict-aliasing -c lltinit.c -o lltinit.o rm -rf libllt.a ar rs libllt.a bitvector.o hashing.o socket.o timefuncs.o ptrhash.o utf8.o ios.o dirpath.o htable.o bitvector-ops.o int2str.o dump.o random.o lltinit.o ar: creating libllt.a make[1]: Leaving directory '/home/ptisnovs/temp/femtolisp/llt' rm -rf libflisp.a ar rs libflisp.a flisp.o builtins.o string.o equalhash.o table.o iostream.o ar: creating libflisp.a gcc -O2 -DNDEBUG -falign-functions -Wall -Wno-strict-aliasing -Illt -DUSE_COMPUTED_GOTO -c flmain.c -o flmain.o gcc -O2 -DNDEBUG -falign-functions -Wall -Wno-strict-aliasing -Illt -DUSE_COMPUTED_GOTO flisp.o builtins.o string.o equalhash.o table.o iostream.o flmain.o -o flisp llt/libllt.a -lm libflisp.a
Samotná definice bootstrapingu vypadá přibližně následovně. Povšimněte si, že se první minimalisticky pojatá verze Femtolispu použije pro vytvoření základní knihovny tvořící prakticky nedílnou součást virtuálního stroje tohoto jazyka:
#!/bin/sh cp flisp.boot flisp.boot.bak echo "Creating stage 0 boot file..." #../../branches/interpreter/femtolisp/flisp mkboot0.lsp system.lsp compiler.lsp > flisp.boot.new ./flisp mkboot0.lsp system.lsp compiler.lsp > flisp.boot.new mv flisp.boot.new flisp.boot echo "Creating stage 1 boot file..." ./flisp mkboot1.lsp echo "Testing..." make test
Na konci se automaticky spustí testy, které ověří základní vlastnosti nově přeloženého interpretru:
cd tests && ../flisp unittest.lsp all tests pass
Výsledkem překladu jsou dva soubory: spustitelný interpret flisp a dále soubor flisp.boot se základními funkcemi, ovšem přeloženými do „bajtkódu“ (nejedná se ovšem o skutečný bajtkód v původním významu tohoto slova). Pro další práci budete skutečně potřebovat pouze tyto dva soubory.
Ověření výsledků překladu:
$ file flisp flisp: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=685356fb92af78d4addae34f30047683e0299afc, for GNU/Linux 3.2.0, not stripped
Nyní si můžeme vyzkoušet spuštění interpretru:
$ ./flisp
Zobrazit by se mělo logo Femtolispu následované výzvou (prompt):
; _ ; |_ _ _ |_ _ | . _ _ ; | (-||||_(_)|__|_)|_) ;-------------------|---------------------------------------------------------- >
Otestujeme, zda interpret reaguje na základní formu:
> (+ 1 2) 3
$ cd tiny $ make gcc -O3 -fomit-frame-pointer -Wall -Wextra lisp.c -o lisp $ ls -l lisp -rwxrwxr-x 1 ptisnovs ptisnovs 31560 Jan 15 17:09 lisp $ ./lisp Welcome to femtoLisp ----------------------------------------------------------
Touto variantou se však nebudeme v dalším textu zabývat. Snad jen stojí za povšimnutí velikost výsledného binárního souboru – relativně malý interpret o velikosti 31560 bajtů.
6. Skutečně minimalistická implementace?
Původně byl Femtolisp pojat (alespoň podle slov svého autora) přísně minimalisticky, a to jak s ohledem na velikost výsledného binárního kódu s jazykem, tak i s ohledem na množství podporovaných knihoven. Postupně se však jak vlastní jazyk, tak i množství podporovaných knihoven rozrostlo, takže Femtolisp již – i přes své jméno – nepatří mezi nejmenší prakticky použitelný dialekt LISPu či Scheme. Vzhledem k tomu, že jsem v minulosti používal jazyky, jejichž velikost spustitelného souboru byla 8kB (klasické verze BASICů), 4kB (základní verze jazyka BASIC) či pouze 1 kB (Forth), pochopitelně mě zajímalo, jak malý či naopak velký je Femtolisp po svém překladu. Ostatně se můžeme podívat do následující tabulky, v níž jsou vypsány velikosti některých malých (podle tvrzení autorů) implementací LISPu a Scheme. Pro porovnání s mainstreamem jsem ještě přidal velikosti interpretrů dalších programovacích jazyků. Všechny získané velikosti přitom platí pro architekturu x86_64, případné balíčky pochází z Linux Mintu (ovšem LISPy a Scheme jsem překládal přímo ze zdrojových kódů):
# | Interpret/VM | Velikost | Poznámka |
---|---|---|---|
1 | Femtolisp | 176 296 | po strip |
2 | tiny Femtolisp | 31 560 | alternativní implementace zmíněná výše |
3 | picolisp | 195 272 | |
4 | tinyscheme | 78 152 | po strip |
5 | lua5.1 | 174 976 | standardní instalace z balíčku |
6 | lua5.2 | 195 416 | standardní instalace z balíčku |
7 | luajit | 445 080 | standardní instalace z balíčku |
8 | python2.7 | 3 674 216 | standardní instalace z balíčku |
9 | python3.8 | 5 490 488 | standardní instalace z balíčku |
Binární kód Femtolispu byl zmenšen příkazem strip, a to z této původní velikosti:
$ ls -l flisp -rwxrwxr-x 1 ptisnovs ptisnovs 205336 Dec 11 11:10 flisp
Na zobrazených přibližně 176 kB:
$ strip flisp $ ls -l flisp -rwxrwxr-x 1 ptisnovs ptisnovs 176296 Dec 11 13:10 flisp
7. Vylepšení REPLu jazyka Femtolisp
Femtolisp není přeložen s podporou knihovny readline, což je patrné i z následujícího výpisu dynamických knihoven, na kterých Femtolisp závisí:
$ ldd flisp linux-vdso.so.1 (0x00007ffd68cb3000) libm.so.6 =→ /lib/x86_64-linux-gnu/libm.so.6 (0x00007f36b36d4000) libc.so.6 =→ /lib/x86_64-linux-gnu/libc.so.6 (0x00007f36b34e2000) /lib64/ld-linux-x86-64.so.2 (0x00007f36b3869000)
Proč je to důležité? Nepodpora readline, mj. znamená, že neexistuje historie příkazového řádku, není možné používat editační příkazy typu Ctrl+A, Ctrl+E, vyhledávání v dříve zadaných příkazech pomocí Ctrl+R atd. A navíc nefunguje automatické doplňování jmen symbolů klávesou Tab. Tyto vlastnosti, které dnes od REPLů prakticky automaticky očekáváme, je možné do jisté míry doplnit externím nástrojem rlwrap. Tomu můžeme předat soubor se symboly pro automatické doplňování. Spustíme tedy flisp a zavoláme funkci environment:
> (environment) (zero? write wchar void vector.map vector->list vector.alloc vector? values untrace vector ulong uint64 uint32 typeof uint16 uint8 traced? trace truncate top-level-exception-handler top-level-value to-proper time.string that table.values table.pairs table.keys table.invert table.foreach table.clone table.foldl table? table tan time.fromstring ... ... ...
Tento seznam symbolů je možné přesměrovat do souboru, který se může jmenovat například environment.txt. Jeho ukázku nalezneme na adrese https://github.com/tisnik/lisp-families/blob/master/femtolisp/environment.txt. Následně flisp ukončíme a spustíme odlišným způsobem:
$ rlwrap -f environment.txt -m -M .scm ./flisp
Zdánlivě nedojde k žádné podstatné změně, ovšem nyní je možné využívat historii příkazového řádku (šipky nahoru, dolů + vyhledávání), editovat obsah příkazového řádku, zavolat externí editor pro delší texty a taktéž používat klávesu Tab pro doplňování jmen symbolů – tedy v naprosté většině případů funkcí, maker a speciálních forem programovacího jazyka.
V dalším textu jsou vypsány vybrané klávesové zkratky, které jsou ve výchozím nastavení použity knihovnou GNU Readline při přepnutí do režimu Emacs (což je výchozí chování).
Příkazy pro přesuny kurzoru
Základní příkazy pro přesun kurzoru používají kombinaci Ctrl+znak, Alt+znak popř. alternativně Esc, znak v případě, že zkratky Alt+znak kolidují s emulátorem terminálu (například vyvolávají příkazy z menu – což je z nějakého důvodu dnes moderní). Pokud je terminál správně nakonfigurován, měly by fungovat i kurzorové šipky a navíc i klávesy Home a End (se zřejmou funkcí):
Klávesa | Význam |
---|---|
Ctrl+B | přesun na předchozí znak |
Ctrl+F | přesun na další znak |
Alt+B | přesun na předchozí slovo |
Alt+F | přesun na další slovo |
Esc, B | shodné s Alt+B |
Esc, F | shodné s Alt+F |
Ctrl+A | přesun na začátek řádku |
Ctrl+E | přesun na konec řádku |
Mazání textu, práce s kill ringem
Pro přesun části textu v rámci editovaného řádku se používá takzvaný kill ring, do něhož se smazaný text uloží. Pro vložení takto smazaného textu do jiné oblasti se používá operace nazvaná yank (odpovídá paste). Některé dále uvedené příkazy dokážou s kill ringem pracovat:
Klávesa | Význam |
---|---|
Ctrl+K | smaže text od kurzoru do konce řádku a uloží ho do kill ringu |
Ctrl+U | smaže text od začátku řádku do pozice kurzoru a uloží ho do kill ringu |
Ctrl+W | smaže předchozí slovo a uloží ho do kill ringu |
Alt+D | smaže následující slovo a uloží ho do kill ringu |
Ctrl+Y | vloží text z kill ringu na místo, na němž se nachází kurzor (yank) |
Alt+Y | po operaci Ctrl+Y dokáže rotovat historií kill ringu a obnovit tak (před)předchozí smazaný text |
Ctrl+D | smaže jeden znak (pokud je ovšem na řádku nějaký obsah, jinak typicky ukončí aplikaci) |
Práce s historií dříve zadaných příkazů
Klávesa | Význam |
---|---|
Ctrl+P | průchod historií – předchozí text |
Ctrl+N | průchod historií – následující text |
Ctrl+R | zpětné (interaktivní) vyhledávání v historii |
Ctrl+G | ukončení režimu vyhledávání |
Některé další dostupné příkazy
Klávesa | Význam |
---|---|
Tab | implicitní klávesa pro zavolání completeru |
Ctrl+T | prohození dvou znaků (před kurzorem a na pozici kurzoru) |
Ctrl+^ | zavolání externího editoru |
Alt+U | text od pozice kurzoru do konce slova se změní NA VERZÁLKY |
Alt+L | text od pozice kurzoru do konce slova se změní na mínusky |
Alt+C | text od pozice kurzoru do konce slova se změní Tak, Že Slova Začínají Velkým Písmenem |
Důležitá i klávesová zkratka Ctrl+^, která zavolá textový editor specifikovaný v proměnné prostředí EDITOR nebo VISUAL. Do editoru lze vložit delší funkci či makro a uložit výsledek, který se v REPLu ihned provede. Při volání rlwrap jsme nastavili jména dočasných souborů tak, aby měly příponu .scm, což zvolenému editoru umožní zvýraznění syntaxe.
8. Základní vlastnosti jazyka Femtolisp
Femtolisp sice ve svém názvu obsahuje LISP, ale samotná sémantika implementovaného jazyka se spíše přibližuje vlastnostem popsaným v R4RS i R5RS, takže jen v krátkosti (většinu příkladů jsme již viděli v některém z předchozích článků). Všechny ukázky jsou zkopírovány přímo z REPLu.
V dále uvedených příkladech budeme používat upravenou formu funkce print, která provede automatické odřádkování:
(define (print item) (princ item) (newline))
(define (print item) (princ item) (newline) "")
Práce s tečka-dvojicemi
Název LISP sice vznikl ze slov LISt Processing, ovšem ve skutečnosti není základním složeným typem LISPů seznam (list), ale takzvaná tečka-dvojice. Seznamy jsou jen jednou formou uspořádání tečka dvojic (další formou mohou být stromy atd.).
(print '(1 . 2)) (1 . 2) (print '(1 . ((2 . 3) . 4))) (1 (2 . 3) . 4) (print '((1 . 2) . (3 . 4))) ((1 . 2) 3 . 4) ; this is NOT proper list (print '(1 . (2 . (3 . nil)))) (1 2 3 . nil) ; this is proper list (print '(1 . (2 . (3 . ())))) (1 2 3) ; this is NOT proper list (print '(1 . (2 . (3 . (4 ()))))) (1 2 3 4 ()) ; this is proper list (print '(1 . (2 . (3 . (4 . ()))))) (1 2 3 4)
Konstrukce tečka dvojic realizovaná formou cons
Tečka-dvojice lze z existujících hodnot a symbolů konstruovat s využitím formy cons:
; cons usage (cons 1 2) (1 . 2) ; another cons usage (cons 1 (cons 2 3)) (1 2 . 3) ; this is proper list (cons 1 (cons 2 (cons 3 '()))) (1 2 3) ; this is proper list (cons 1 '(2 3 4)) (1 2 3 4) ; this is NOT proper list (cons 1 (cons 2 (cons 3 4))) (1 2 3 . 4)
Konstrukce seznamů
Z tečka-dvojic lze sestrojit seznamy, což bylo ukázáno v posledním příkladu:
; this is proper list (print '(1 . (2 . (3 . (4 . ()))))) (1 2 3 4)
Vzhledem k tomu, že se seznamy používají velmi často (a to i pro vytváření vyhodnocovaných forem), existuje i kratší způsob jejich zápisu:
; empty list '() () ; a list '(1 2 3 4) (1 2 3 4) ; another list (list 1 2 3 4) (1 2 3 4)
Základní operace se seznamy – car a cdr
Ze seznamů lze získat první prvek formou car a zbylé prvky formou cdr. Existují i další kombinace car a cdr zapisované jako cadr, cddr atd.:
; create list and assign it to symbol (define a '(1 2 3 4)) (1 2 3 4) ; get the first item (car a) 1 ; get the rest of a list (cdr a) (2 3 4) ; combination of car+cdr (cadr a) 2 ; combination of cdr+cdr (cddr a) (3 4)
9. Funkce a speciální formy
Podobně jako u každého dialektu programovacího jazyka LISP resp. Scheme, i v případě Femtolispu se program skládá především z funkcí. Ty mohou být anonymní (nepojmenované) či naopak pojmenované. Nejprve se zabývejme pojmenovanými funkcemi, protože ty se chovají prakticky stejně, jako běžné funkce v jiných programovacích jazycích – pouze způsob jejich zápisu je odlišný. Pojmenované funkce se definují pomocí speciální formy define, za níž v závorkách následuje jméno funkce. Každá funkce může mít libovolný počet parametrů, jejichž jména se uvádí v seznamu ihned za pojmenováním funkce. Poslední částí formy define je v tomto případě tělo funkce, přičemž po zavolání funkce se vyhodnocená forma vrátí jako její výsledek (nikde se tedy nezapisuje slovo „return“ ani nic s podobným významem – ostatně podobný způsob je použit i v Rustu):
; one-liner function (define (add x y) (+ x y)) ; function written on more lines (define (mul x y) (* x y))
; function written on more lines using lambda (define div (lambda (x y) (* x y)))
Zavolání funkce je jednoduché – používá se stále ten samý formát seznamu, na jehož prvním místě je jméno funkce a za ním následují parametry:
(print (add 1 2)) (print (mul 6 7)) (print (div 10 3))
Kromě pojmenovaných funkcí, které jsme si již představili v předchozím textu, je možné ve Femtolispu použít i funkce anonymní, tj. funkce, které nejsou navázány na žádné jméno. Pro tento účel se používá přímo lambda výraz (bez define), podobně jako v každém ortodoxním Lispu (snad kromě PicoLispu):
; anonymous function is a value (lambda (x y) (+ x y)) ; call anonymous function (print (lambda (x y) (+ x y)))
Další důležitou vlastností jazyka implementovaného ve Femtolispu, s níž se dnes (znovu) seznámíme, je použití takzvaných speciálních forem. Ze syntaktického hlediska jsou speciální formy zapisovány naprosto stejným způsobem jako běžné funkce, ovšem existuje zde jeden významný rozdíl – zatímco u funkcí jsou všechny jejich parametry nejdříve vyhodnoceny, u speciálních forem k tomuto vyhodnocení obecně nedochází, resp. jsou vyhodnoceny pouze některé parametry (které konkrétně, to závisí na tom, o jakou speciální formu se jedná). S některými speciálními formami jsme se již setkali, především s formou define či let, ovšem existují i formy další – cond, if, and, lambda, quote, do atd.
Speciální forma cond:
(define (sgn n) (cond ((< n 0) 'negative) ((> n 0) 'positive) ((zero? n) 'zero)))
Alternativní forma s větví else:
(define (sgn-2 n) (cond ((< n 0) 'negative) ((> n 0) 'positive) (#t 'zero)))
Speciální forma case:
(print (case (* 2 3) ((2 3 5 7) 'prime) ((1 4 6 8 9) 'composite)))
(print (case (car '(a y x)) ((a e i o u) 'vowel) ((w y) 'semivowel) (else 'consonant)))
Speciální forma do pro realizaci smyček:
(define (compute-pi n) (let ((pi 4.0)) (do ((i 3 (+ i 2))) ((> i (+ n 2))) (set! pi (* pi (/ (- i 1) i) (/ (+ i 1) i)))) pi)) (do ((n 1 (* n 2))) ((> n 10000000)) (princ n) (princ " ") (princ (compute-pi n)) (newline))
Pojmenované let, taktéž pro realizaci smyček:
(define (let-loop) (let loop ((i 0)) (cond ((> i 10)) (else (print i) (loop (+ i 1))))))
Smyčka typu repeat n:
(define (call-n-times n proc) (let loop ((n n)) (unless (zero? n) (proc) (loop (- n 1))))) (define (print-hello) (print "Hello")) (call-n-times 10 print-hello)
Ještě lepší řešení pro funkci s argumenty:
(define (call-n-times n proc argument) (let loop ((n n)) (unless (zero? n) (proc argument) (loop (- n 1))))) (call-n-times 10 print "Hello")
10. Pojmenované funkce s proměnným počtem parametrů
Vzhledem k tomu, že speciální formu define (ve variantě, kdy se definuje funkce) lze kdykoli zapsat s využitím speciální formy lambda, je v programovacím jazyku Femtolisp možné nadefinovat pojmenovanou funkci akceptující proměnný (tj. v krajním případě i nulový) počet parametrů, z nichž je při volání funkce automaticky vytvořen seznam, se kterým je možné v těle funkce libovolným způsobem manipulovat. Syntakticky vypadá definice takové funkce následovně:
(define (jméno funkce . parametr) [tělo funkce])
Což je ekvivalentní zápisu, který již známe z předchozího textu:
(define jméno funkce (lambda parametr [tělo funkce]))
Následuje příklad definice funkce s proměnným počtem parametrů:
; funkce vracející počet skutečně předaných parametrů (define (foo . parametry) (length parametry))
Zavolání této funkce bez parametrů vrátí nulu:
(foo) 0
Předat můžeme jeden parametr:
(foo 42) 1
A samozřejmě i větší počet parametrů:
(foo 1 2) 2 (foo "bar" "baz") 2 (foo '(1 2 3 4)) 1
Ukažme si ještě alternativní formu zápisu využívající kombinace define a lambda:
; alternativní forma zápisu (define foo (lambda parametry (length parametry))) ; volání funkce bez parametrů (foo) 0 ; volání funkce se třemi parametry (zde se jedná o trojici symbolů) (foo 'a 'b 'c) 3
11. Povinné a nepovinné parametry pojmenovaných funkcí
Při definici funkcí lze určit i nepovinné parametry. Hodnoty nepovinných parametrů se uloží do seznamu, jehož jméno je uvedeno za tečkou v seznamu parametrů. Jedná se tedy o kombinaci klasických funkcí s konstantním počtem povinných parametrů a funkcí s proměnným počtem parametrů.
Podívejme se na jednoduchý příklad funkcí, které se liší jak počtem parametrů, tak i tím, zda akceptují nepovinné parametry:
(define (f1) (print "no parameters")) (define (f2 a) (print "one parameter") (print a)) (define (f3 a b) (print "two parameters") (print a) (print b)) (define (f4 a . b) (print "at least one parameter") (print a) (print b)) (define (f5 a b . c) (print "at least two parameters") (print a) (print b) (print c)) (f1) (f2 10) (f3 1 2) (f4 1) (f4 1 2) (f4 1 2 3) (f5 1 2) (f5 1 2 3) (f5 1 2 3 4)
Výsledky získané po spuštění skriptu:
(f1) no parameters (f2 10) one parameter 10 (f3 1 2) two parameters 1 2 (f4 1) at least one parameter 1 () (f4 1 2) at least one parameter 1 (2) (f4 1 2 3) at least one parameter 1 (2 3) (f5 1 2) at least two parameters 1 2 () (f5 1 2 3) at least two parameters 1 2 (3) (f5 1 2 3 4) at least two parameters 1 2 (3 4)
12. Koncová rekurze
V naprosté většině algoritmů se objevují bloky kódu, které se mají iterativně opakovat. Při programování s využitím funkcionálního paradigmatu se iterace vyjadřuje formou rekurze. Ta je samozřejmě ve Scheme podporována (mezi jediné známější jazyky, které rekurzi nepodporovaly, patřil původní FORTRAN a Basic), ovšem specifikace jazyka Scheme jde ještě dále, protože určuje, ve kterých případech je skutečná rekurze (při níž se parametry a návratové adresy musí ukládat na zásobník) nahrazena takzvanou koncovou rekurzí, což zjednodušeně řečeno znamená, že se namísto skutečného rekurzivního volání funkce interně provede obyčejný skok (koncový skok či koncové volání) bez nutnosti alokace místa na zásobníku pro parametry volané funkce a návratové adresy. Touto specifikací se také do značné míry řídí Femtolisp.
Koncová rekurze představuje při správném použití velmi silnou programovací techniku, protože umožňuje zapisovat mnoho algoritmů v mnohdy elegantní rekurzivní formě, ovšem skutečné zpracování takto zapsaných algoritmů je stejně efektivní jako provádění programové smyčky (každou koncovou rekurzi lze nahradit smyčkou a naopak).
Následující funkce plus sice rekurzivně volá sebe sama, ovšem z pohledu sémantiky se jedná o běžnou iteraci, protože volání plus lze nahradit skokem – není zapotřebí si pamatovat předchozí výsledky:
; A classic example taken from MIT 6.001 course (define (plus x y) (if (= x 0) y (plus (- x 1) (+ y 1)))) (princ (plus 10000000 10000000)) (newline)
Při nepatrné úpravě ovšem získáme rekurzivní variantu, v níž je nutné si pamatovat mezivýsledky získané při fázi navíjení:
; A classic example taken from MIT 6.001 course (define (plus x y) (if (= x 0) y (+ 1 (plus (- x 1) y)))) (princ (plus 10000000 10000000)) (newline)
Dalším klasickým příkladem rozdílu mezi normální (plnou, skutečnou) rekurzí a koncovou rekurzí je výpočet faktoriálu. Ten můžeme zapsat mnoha způsoby, například (jak je to v matematice obvyklé), rekurzivně:
(define (factorial n) (if (= n 0) ; podmínka pro ukončení rekurzivního zanořování 1 ; faktoriál nuly je definitoricky roven jedné (* n (factorial (- n 1)))))
Z teoretického hlediska není na výše uvedené funkci nic nekorektního, ovšem při jejím praktickém používání brzy narazíme na limit způsobený omezenou velikostí zásobníku.
Výše uvedený rekurzivní výpočet lze relativně malou úpravou převést na výpočet který (alespoň v programovacím jazyce Scheme) vede na koncové volání, což mj. znamená, že paměťové (prostorové) nároky tohoto programu jsou konstantní:
; výpočet faktoriálu využívající koncového volání (define (factorial n) (let fact-iter ( ; pomocná vnitřní funkce (n n) ; počitadlo iterací (result 1)) ; průběžný výsledek (if (= n 0) ; po dosažení koncového stavu result ; se vrátí průběžný výsledek (fact-iter (- n 1) (* n result)) ; koncové volání )))
Zásobník používaný v rekurzivních variantách není nijak omezený (na rozdíl od mnoha dalších programovacích jazyků). Takže se může stát, že proces začne používat swap. Prozatím ve Femtolispu neexistuje možnost omezení velikosti zásobníku (na daný počet prvků) tak, jak to má například Guile:
(define (plus x y) (if (= x 0) y (plus (- x 1) (+ y 1)))) (define (test) (display (plus 10000000 10000000))) (define (handler) (display "Stack overflow\n")) (call-with-stack-overflow-handler 1000 test handler)
13. Typový systém Femtolispu
Femtolisp je sice odvozen od programovacího jazyka Scheme, ale ve skutečnosti postrádá například plnou „numerickou věž“, což znamená, že zde neexistuje úplná hierarchie numerických datových typů (celá čísla, zlomky, reálná čísla, komplexní čísla). Většina aritmetických operací je prováděna s hodnotami s plovoucí řádovou čárkou zpracovatelnými matematickým koprocesorem popř. se operace provádí s čísly typu int. To mj. znamená, že se Femtolisp bude chovat odlišně, než například Guile. Příkladem může být jednoduchý výpočet podílu.
Femtolisp:
(/ 4 3) 1.3333333333333333
Guile:
(/ 4 3) 4/3
Test na přetečení celých čísel:
(define (print item) (princ item) (newline)) (do ((n 1 (* n 2))) ((> n 100000000000000000000)) (print n))
Po spuštění ve Femtolispu je patrné, že se korektně detekovalo přetečení:
1 2 4 8 16 32 ... ... ... 72057594037927936 144115188075855872 288230376151711744 576460752303423488 Press ENTER or type command to continue parse-error: read: overflow in numeric constant 100000000000000000000 in file int_size.scm
Podívejme se nyní na další datové typy a jejich hodnoty. Snadno zjistíme, že datový typ (a současně i hodnota) nil není přímo podporován – i v tomto ohledu se tedy blížíme spíše ke Scheme než ke klasickým LISPům:
nil eval: variable nil has no value #0 (lambda)
Pro reprezentaci pravdivostních hodnot se používají symboly #t a #f, které se vyhodnocují samy na sebe:
#t #t #f #f
Specifický význam má i prázdný seznam, jenž je zapisován takto:
'() ()
Nebo takto:
() ()
Podporovány jsou pochopitelně seznamy, ovšem vzhledem k tomu, že jak seznamy, tak i formy se zapisují do hranatých závorek, je u seznamů nutné zakázat jejich vyhodnocování:
(1 2 3) type error: apply: expected function, got 1 #0 (lambda) '(1 2 3) (1 2 3)
Femtolisp podporuje i zápis vektorů, resp. přesněji řečeno literálů představujících vektory:
[1 2 3] [1 2 3]
Řetězce se zapisují do uvozovek, jak je to běžné.
Ve Femtolispu je možné typ hodnoty (popř. skupinu typů) zjistit s využitím několika predikátů, což jsou formy, jejichž jména končí otazníkem:
Predikát |
---|
atom? |
list? |
vector? |
null? |
number? |
fixnum? |
Tyto predikáty si můžeme relativně snadno otestovat, a to pro hodnoty libovolného typu:
(define (print item) (princ item) (newline)) (define nil '()) (print "atom?") (print (atom? nil)) (print (atom? #t)) (print (atom? 42)) (print (atom? 3.14)) (print (atom? "string")) (print (atom? '(1 2 3))) (print (atom? [1 2 3])) (newline) (print "list?") (print (list? nil)) (print (list? #t)) (print (list? 42)) (print (list? 3.14)) (print (list? "string")) (print (list? '(1 2 3))) (print (list? [1 2 3])) (newline) (print "vector?") (print (vector? nil)) (print (vector? #t)) (print (vector? 42)) (print (vector? 3.14)) (print (vector? "string")) (print (vector? '(1 2 3))) (print (vector? [1 2 3])) (newline) (print "null?") (print (null? nil)) (print (null? #t)) (print (null? 42)) (print (null? 3.14)) (print (null? "string")) (print (null? '(1 2 3))) (print (null? [1 2 3])) (newline) (print "number?") (print (number? nil)) (print (number? #t)) (print (number? 42)) (print (number? 3.14)) (print (number? "string")) (print (number? '(1 2 3))) (print (number? [1 2 3])) (newline) (print "fixnum?") (print (fixnum? nil)) (print (fixnum? #t)) (print (fixnum? 42)) (print (fixnum? 3.14)) (print (fixnum? "string")) (print (fixnum? '(1 2 3))) (print (fixnum? [1 2 3])) (newline) (print "zero?") (print (zero? 0)) (print (zero? 42)) (newline)
Výsledky jsou vypsány na jednotlivé řádky, což ovšem není příliš přehledné:
atom? #t #t #t #t #t #f #t list? #t #f #f #f #f #t #f vector? #f #f #f #f #f #f #t null? #t #f #f #f #f #f #f number? #f #f #t #t #f #f #f fixnum? #f #f #t #f #f #f #f zero? #t #f
Přehlednější je výpis v tabulkovém formátu:
Hodnota | atom? | list? | vector? | null? | number? | fixnum? |
---|---|---|---|---|---|---|
'() | #t | #t | #f | #t | #f | #f |
#t | #t | #f | #f | #f | #f | #f |
42 | #t | #f | #f | #f | #t | #t |
3.14 | #t | #f | #f | #f | #t | #f |
„string“ | #t | #f | #f | #f | #f | #f |
'(1 2 3) | #f | #t | #f | #f | #f | #f |
[1 2 3] | #t | #f | #t | #f | #f | #f |
14. Lokální rozsah proměnných
Jazyk Scheme (do kterého Femtolisp spadá, i přes své jméno) je, na rozdíl od původních LISPů, založen na lokálním rozsahu proměnných (local scope). Můžeme si to ostatně relativně snadno ukázat na následujícím demonstračním příkladu, v němž je uvnitř funkce add použit lokální rozsah, v rámci něhož je vyhodnocována proměnná x:
(define x 1) (define y 2) (define (add x y) ; rozsah (scope) je lokální! (set! x (+ x y)) x) (print (add x y)) (print (add x y)) (set! x 10) (print (add x y)) (print (add x y))
Po spuštění tohoto příkladu se vypíše:
3 3 12 12
Příklad s globálními a lokálními proměnnými:
Příklad s globálními a lokálními proměnnými:
(define x 1) (define y 2) (define (add x y) (+ x y)) (print (add x y)) (print (let ((x 10) (y 20)) (add x y))) (set! x 10) (print (add x y)) (print (let ((x 10) (y 20)) (add x y))) (print (let ((x 100)) (add x y)))
Po spuštění tohoto demonstračníh příkladu se vypíše:
3 30 12 30 102
(define (larger-than limit) (lambda (value) (> value limit))) (print ((larger-than 5) 0)) (print ((larger-than 5) 10)) (print (filter (larger-than 5) '(1 2 3 4 5 6 7 8 9 10)))
S těmito výsledky:
#f #t (6 7 8 9 10) (6 7 8 9 10)
Další, nepatrně složitější implementace uzávěrů:
(define counter (let ((i -1)) (lambda () (set! i (+ i 1)) i))) (print (counter)) (print (counter)) (print (counter))
S výsledky:
0 1 2
(define (get-counter) (let ((i -1)) (lambda () (set! i (+ i 1)) i))) (define counter1 (get-counter)) (define counter2 (get-counter)) (print (counter1)) (print (counter1)) (print (counter1)) (print (counter2)) (print (counter2)) (print (counter2)) (print (counter1)) (print (counter1)) (print (counter1))
Výsledky činnosti dvou čítačů:
0 1 2 0 1 2 3 4 5
Uzávěry ve skutečnosti nejsou „obyčejnými“ funkcemi, protože je lze současně považovat za úložiště dat. Viz například následující příklad, který je uváděn ve slavném kurzu 6.001 na MIT (pravděpodobně nejlépe strukturovaném kurzu o informatice vůbec). V tomto příkladu je cons- nositelem dat o tečka-dvojici:
(define (cons- x y) (lambda (m) (if (= m 0) x y))) (define (car- z) (z 0)) (define (cdr- z) (z 1)) (princ (cons- 1 2)) (newline) (princ (car- (cons- 1 2))) (newline) (princ (cdr- (cons- 1 2))) (newline)
15. Makrosystém
Ve Femtolispu jsou plně podporována i makra, která částečně vychází ze systému maker Common Lispu. S makry souvisí i použití znaků nazývaných quote a quasiquote, které umožňují ve fázi expanze maker vkládání hodnot či symbolů do expandované části kódu. Jen ve stručnosti si ukažme použití quote a quasiquote (nejenom) při konstrukci seznamů:
(define b (list 1 2 3)) (print "quote:") (print '(a b c)) (print '(a ,b c)) (print '(a ,@b c)) (newline) (print "quasiquote:") (print `(a b c)) (print `(a ,b c)) (print `(a ,@b c)) (newline)
Z výsledků je patrné, jak znaky „`“, „,“ a „,@“ ovlivňují expanzi prvků v seznamu. To neplatí pro klasický znak „'“ (quote), který zcela zakazuje vyhodnocování prvků v seznamu (první tři výsledky):
quote: (a b c) (a ,b c) (a ,@b c) quasiquote: (a b c) (a (1 2 3) c) (a 1 2 3 c)
Následuje příklad makra s implementací programové smyčky typu while. Povšimněte si, že se v makru skutečně musí použít quasiquote, uvnitř quasiquote pak „,symbol“ a „,@symbol“:
(define-macro (while- test . forms) `((label -loop- (lambda () (if ,test (begin ,@forms (-loop-)) ()))))) (define (test-while) (set! i 0) (while (< i 10000000) (set! i (+ i 1))) (princ i) (newline))
16. Reálné použití Femtolispu
Femtolisp, pokud by byl používán samostatně jako jeden z dialektů LISPu resp. Scheme, ve skutečnosti nepřináší žádné nové myšlenky a pro praktické použití je (alespoň podle mého názoru) lepší použít jinou implementaci – Guile (snadná vestavitelnost), Chicken Scheme (kvalitní překladač), Racket (prakticky zaměřeno, podpora dalších (meta)jazyků) či Common Lisp (podle toho, co je konkrétně od implementace jazyka vyžadováno). Ovšem Femtolisp zabudovaný přímo v jazyce Julia otevírá zcela nové možnosti například při testování nových syntaktických prvků, transformacích kódu před jeho dalším zpracováním, dokonce i testováním nových typových systémů atd.
17. Repositář s demonstračními příklady
Zdrojové kódy všech dnes použitých demonstračních příkladů určených pro spuštění ve Femtolispu byly uloženy do Git repositáře, který je dostupný na adrese https://github.com/tisnik/lisp-families.git (stále na GitHubu :-). V případě, že nebudete chtít klonovat celý repositář (ten je ovšem – alespoň prozatím – velmi malý, můžete namísto toho použít odkazy na jednotlivé příklady, které naleznete v následující tabulce:
18. Předchozí části seriálu
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):
- 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/ - PicoLisp: minimalistický a přitom překvapivě výkonný interpret Lispu
https://www.root.cz/clanky/picolisp-minimalisticky-a-pritom-prekvapive-vykonny-interpret-lispu/ - 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/ - 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/ - GNU Guile – interpret Scheme vestavitelný do nativních aplikací
https://www.root.cz/clanky/gnu-guile-interpret-scheme-vestavitelny-do-nativnich-aplikaci/ - 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/ - 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/ - Jazyk Kawa v ekosystému virtuálního stroje Javy
https://www.root.cz/clanky/jazyk-kawa-v-ekosystemu-virtualniho-stroje-javy/ - 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/ - 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/ - Makra v Racketu i v dalších lispovských jazycích
https://www.root.cz/clanky/makra-v-racketu-i-v-dalsich-lispovskych-jazycich/ - Základní knihovna jazyka Racket
https://www.root.cz/clanky/zakladni-knihovna-jazyka-racket/ - Jazyk Joker: dialekt Clojure naprogramovaný v Go
https://www.root.cz/clanky/jazyk-joker-dialekt-clojure-naprogramovany-v-go/ - 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/ - 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/ - Interlisp aneb oživujeme dinosaura
https://www.root.cz/clanky/interlisp-aneb-ozivujeme-dinosaura/ - 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/ - 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/
Články o Elispu:
- Ú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/ - Úpravy Emacsu s Emacs Lisp: základní konstrukce jazyka
https://www.root.cz/clanky/upravy-emacsu-s-emacs-lisp-zakladni-konstrukce-jazyka/ - Ú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/ - Ú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/ - Úpravy Emacsu s Emacs Lisp: dokončení popisu Emacs Lispu
https://www.root.cz/clanky/upravy-emacsu-s-emacs-lisp-dokonceni-popisu-emacs-lispu/ - Ú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/
19. Literatura
- Peter Seibel
„Practical Common Lisp“
2009 - Paul Graham
„ANSI Common Lisp“
1995 - Gerald Gazdar
„Natural Language Processing in Lisp: An Introduction to Computational Linguistics“
1989 - Peter Norvig
„Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp“
1991 - Alex Mileler et.al.
„Clojure Applied: From Practice to Practitioner“
2015 - „Living Clojure: An Introduction and Training Plan for Developers“
2015 - Dmitri Sotnikov
„Web Development with Clojure: Build Bulletproof Web Apps with Less Code“
2016 - McCarthy
„Recursive functions of symbolic expressions and their computation by machine, part I“
1960 - R. Kent Dybvig
„The Scheme Programming Language“
2009 - Max Hailperin
„Concrete Abstractions“
1998 - Guy L. Steele
„History of Scheme“
2006, Sun Microsystems Laboratories - Kolář J., Muller K.:
„Speciální programovací jazyky“
Praha 1981 - „AutoLISP Release 9, Programmer's reference“
Autodesk Ltd., October 1987 - „AutoLISP Release 10, Programmer's reference“
Autodesk Ltd., September 1988 - McCarthy, John; Abrahams, Paul W.; Edwards, Daniel J.; Hart, Timothy P.; Levin, Michael I.
„LISP 1.5 Programmer's Manual“
MIT Press. ISBN 0 262 130 1 1 4 - Carl Hewitt; Peter Bishop and Richard Steiger
„A Universal Modular Actor Formalism for Artificial Intelligence“
1973 - Feiman, J.
„The Gartner Programming Language Survey (October 2001)“
Gartner Advisory - Harold Abelson, Gerald Jay Sussman, Julie Sussman:
Structure and Interpretation of Computer Programs
MIT Press. 1985, 1996 (a možná vyšel i další přetisk) - Paul Graham
On Lisp
Prentice Hall, 1993
Dostupné online na adrese http://www.paulgraham.com/onlisptext.html - David S. Touretzky
Common LISP: A Gentle Introduction to Symbolic Computation (Dover Books on Engineering)
- Peter Norvig
Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp - Patrick Winston, Berthold Horn
Lisp (3rd Edition)
ISBN-13: 978–0201083194, ISBN-10: 0201083191 - Matthias Felleisen, David Van Horn, Dr. Conrad Barski
Realm of Racket: Learn to Program, One Game at a Time!
ISBN-13: 978–1593274917, ISBN-10: 1593274912
20. Odkazy na Internetu
- The Evolution of Lisp
https://www.csee.umbc.edu/courses/331/resources/papers/Evolution-of-Lisp.pdf - LISP
https://taoofmac.com/space/dev/lisp - Repositář projektu femtolisp
https://github.com/JeffBezanson/femtolisp - Femtolisp – lightweight, robust lisp interpreter built on reusable C libraries
https://www.findbestopensource.com/product/femtolisp - YCombinator: Femtolisp: A lightweight, robust, scheme-like Lisp implementation
https://news.ycombinator.com/item?id=22094722 - Learning Julia by Anshul Joshi, Rahul Lakhanpal: Femtolisp
https://www.oreilly.com/library/view/learning-julia/9781785883279/2e85442f-d100–4b53-b8f7–7d20d62f0255.xhtml - The role of femtolisp in Julia?
https://discourse.julialang.org/t/the-role-of-femtolisp-in-julia/1902 - LispSyntax.jl: A clojure-like lisp syntax for julia
https://github.com/swadey/LispSyntax.jl - 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 - Interlisp.org: Dedicated to Restoring and Preserving the Interlisp experience
https://github.com/Interlisp - Warren Teitelman
https://en.wikipedia.org/wiki/Warren_Teitelman - InterLISP/65
http://www.atarimania.com/utility-atari-400–800-xl-xe-interlisp-65_12477.html - Lisp Editing in the 80s – Interlisp SEdit (Video)
https://www.youtube.com/watch?v=2qsmF8HHskg - Inter-LISP
http://www.atarimania.com/utility-atari-400–800-xl-xe-inter-lisp_29354.html - InterLISP 65 Editing (video)
https://www.youtube.com/watch?v=nY_hcazo86A - Datasoft INTER-LISP/65 (Atari Age, chat)
https://atariage.com/forums/topic/116093-datasoft-inter-lisp65/ - Marvin Minsky – The beauty of the Lisp language (44/151)
https://www.youtube.com/watch?v=YaWVHyIBVeI - History of LISP (Interlisp)
http://www.softwarepreservation.org/projects/LISP/index.html#INTERLISP_ - Computer-Assisted Instruction (Bits and Bytes, Episode 7)
https://www.youtube.com/watch?v=eURtTV_qKw8 - 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/ - Gambit in the browser
https://feeley.github.io/gambit-in-the-browser/ - A Tour of Scheme in Gambit
http://dynamo.iro.umontreal.ca/wiki/images/a/a7/A_Tour_of_Scheme_in_Gambit.pdf - Gambit Scheme: Inside Out
http://www.iro.umontreal.ca/~gambit/Gambit-inside-out.pdf - Gambit Internal Documentation
http://dynamo.iro.umontreal.ca/wiki/index.php/Internal_Documentation - clojure-scheme: Compiling to Native Code via Scheme
http://www.iro.umontreal.ca/~gambit/Sorenson-Clojure-to-Native-via-Scheme.pdf - Gauche – a Scheme implementation
http://practical-scheme.net/gauche/ - Scheme48
https://s48.org/ - SISC (Second Interpreter of Scheme)
http://sisc-scheme.org/ - The SCM Implementation of Scheme
https://people.csail.mit.edu/jaffer/SCM.html - Ypsilon – The ultimate script language system for the video pinball fourth generation
http://www.littlewingpinball.com/doc/en/ypsilon/index.html - Chicken Scheme
https://call-cc.org/ - Eggs Unlimited
http://wiki.call-cc.org/chicken-projects/egg-index-5.html - Chicken Scheme Wiki
https://wiki.call-cc.org/ - CHICKEN for Python programmers
https://wiki.call-cc.org/chicken-for-python-programmers - Programming for Performance
http://wiki.call-cc.org/programming-for-performance - Using the compiler
https://wiki.call-cc.org/man/4/Using%20the%20compiler - CHICKEN Scheme tutorials
https://wiki.call-cc.org/tutorials - Traditional Turtles
https://docs.racket-lang.org/turtles/Traditional_Turtles.html - [racket] How best to repeat a function call n times?
https://lists.racket-lang.org/users/archive/2014-September/064203.html - Racket: Macros
https://www.it.uu.se/edu/course/homepage/avfunpro/ht13/lectures/Racket-3-Macros.pdf - Beautiful Racket / explainers: Macros
https://beautifulracket.com/explainer/macros.html - Macros (dokumentace k Racketu)
https://docs.racket-lang.org/guide/macros.html - Model syntaxe jazyka Racket
https://docs.racket-lang.org/reference/syntax-model.html - Syntax Objects
https://docs.racket-lang.org/guide/stx-obj.html - Tech behind Tech: Clojure Macros Simplified
http://techbehindtech.com/2010/09/28/clojure-macros-simplified/ - Fatvat – Exploring functional programming: Clojure Macros
http://www.fatvat.co.uk/2009/02/clojure-macros.html - Beautiful Racket: an introduction to language-oriented programming using Racket
https://beautifulracket.com/ - Stránky projektu Racket
https://racket-lang.org/ - Dokumentace k projektu Racket
https://docs.racket-lang.org/index.html - Seznam dostupných balíčků pro Racket
https://pkgs.racket-lang.org/ - Racket na Wikipedii
https://en.wikipedia.org/wiki/Racket_(programming_language) - Vector Library (R7RS-compatible)
https://srfi.schemers.org/srfi-133/srfi-133.html - Blogy o Racketu a navazujících technologiích
https://blog.racket-lang.org/ - Prográmky psané v Racketu na RosettaCode
http://rosettacode.org/wiki/Category:Racket - Fear of Macros
https://www.greghendershott.com/fear-of-macros/ - Rackjure
https://github.com/greghendershott/rackjure - 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/ - Racket News
https://racket-news.com/ - Racket: Lisp for learning
https://lwn.net/Articles/795385/ - Future of Racket
https://www.greghendershott.com/2019/07/future-of-racket.html - Vectors (pro Gauche)
https://practical-scheme.net/gauche/man/gauche-refe/Vectors.html - Kawa: Compiling Scheme to Java
https://www.mit.edu/afs.new/sipb/project/kawa/doc/kawa-tour.html - Kawa in Languages shootout
http://per.bothner.com/blog/2010/Kawa-in-shootout/ - Kawa 2.0 Supports Scheme R7RS
https://developers.slashdot.org/story/14/12/13/2259225/kawa-20-supports-scheme-r7rs/ - Kawa — fast scripting on the Java platform
https://lwn.net/Articles/623349/ - Tail call (a její optimalizace)
https://en.wikipedia.org/wiki/Tail_call - SLIME (Wikipedia)
http://en.wikipedia.org/wiki/SLIME - slime.vim
http://s3.amazonaws.com/mps/slime.vim - What are the best scheme implementations?
https://www.slant.co/topics/5282/~scheme-implementations - Bigloo homepage
http://www-sop.inria.fr/mimosa/fp/Bigloo/ - FTP s tarbally Bigloo
ftp://ftp-sop.inria.fr/indes/fp/Bigloo - GOTO 2018 • Functional Programming in 40 Minutes • Russ Olsen
https://www.youtube.com/watch?v=0if71HOyVjY - TinyScheme (stránka na Sourceforge)
http://tinyscheme.sourceforge.net/home.html - Embedding Tiny Scheme in a Game
http://www.silicondelight.com/embedding-tiny-scheme-in-a-game/ - Embedding Scheme for a game mission scripting DSL
http://carloscarrasco.com/embedding-scheme-for-a-game-mission-scripting-dsl.html - Všechny verze TinyScheme na SourceForge
https://sourceforge.net/projects/tinyscheme/files/tinyscheme/ - Fork TinyScheme na GitHubu
https://github.com/yawnt/tinyscheme - Ackermannova funkce
https://cs.wikipedia.org/wiki/Ackermannova_funkce - Ackermann function na Rosetta Code
https://rosettacode.org/wiki/Ackermann_function#Scheme - Success Stories (lisp.org)
https://lisp-lang.org/success/ - Allegro Common Lisp Success Stories
https://franz.com/success/ - Clojure Success Stories
https://clojure.org/community/success_stories - Scheme Quick Reference
https://www.st.cs.uni-saarland.de/edu/config-ss04/scheme-quickref.pdf - Slajdy o Scheme (od slajdu číslo 15)
https://docs.google.com/presentation/d/1abmDnKjrq1tcjGvvRNAKhOiSTSE2lyagtcEPal07Gbo/edit - Scheme Cheat Sheet
https://github.com/smythp/scheme-cheat-sheet - Embedding Lua, embedding Guile
http://puntoblogspot.blogspot.com/2013/04/embedding-lua-embedding-guile.html - Lambda Papers
https://en.wikisource.org/wiki/Lambda_Papers - Revised7Report on the Algorithmic Language Scheme
https://small.r7rs.org/attachment/r7rs.pdf - Video Lectures (MIT, SICP 2005)
https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6–001-structure-and-interpretation-of-computer-programs-spring-2005/video-lectures/ - Why is Scheme my first language in university?
https://softwareengineering.stackexchange.com/questions/115252/why-is-scheme-my-first-language-in-university - The Perils of JavaSchools
https://www.joelonsoftware.com/2005/12/29/the-perils-of-javaschools-2/ - How to Design Programs, Second Edition
https://htdp.org/2019–02–24/index.html - LilyPond
http://lilypond.org/ - LilyPond — Extending (přes Scheme)
http://lilypond.org/doc/v2.18/Documentation/extending/scheme-tutorial - Scheme in LilyPond
http://lilypond.org/doc/v2.18/Documentation/extending/scheme-in-lilypond - GnuCash
http://www.gnucash.org/ - Custom Reports (in GNU Cash)
https://wiki.gnucash.org/wiki/Custom_Reports - Program by Design
https://programbydesign.org/ - SchemePy
https://pypi.org/project/SchemePy/ - LISP FQA: Section – [1–5] What is the „minimal“ set of primitives needed for a Lisp interpreter?
http://www.faqs.org/faqs/lisp-faq/part1/section-6.html - femtolisp
https://github.com/JeffBezanson/femtolisp - (How to Write a (Lisp) Interpreter (in Python))
http://norvig.com/lispy.html - Repositář s Guile Emacsem
http://git.hcoop.net/?p=bpt/guile.git - Interacting with Guile Compound Data Types in C
http://www.lonelycactus.com/guilebook/x1555.html - Calling Guile functions from C
http://www.lonelycactus.com/guilebook/c1204.html#SECCALLGUILEFUNC - Arrays, and other compound data types
http://www.lonelycactus.com/guilebook/charrays.html - Interacting with Guile Compound Data Types in C
http://www.lonelycactus.com/guilebook/x1555.html - Guile Reference Manual
https://www.gnu.org/software/guile/manual/html_node/index.html - Scheme: Summary of Common Syntax
https://www.gnu.org/software/guile/manual/html_node/Syntax-Summary.html#Syntax-Summary - Scripting with Guile: Extension language enhances C and Scheme
https://www.ibm.com/developerworks/library/l-guile/index.html - Having fun with Guile: a tutorial
http://dustycloud.org/misc/guile-tutorial.html - Guile: Loading Readline Support
https://www.gnu.org/software/guile/manual/html_node/Loading-Readline-Support.html#Loading-Readline-Support - lispy
https://pypi.org/project/lispy/ - Lython
https://pypi.org/project/Lython/ - Lizpop
https://pypi.org/project/lizpop/ - Budoucnost programovacích jazyků
http://www.knesl.com/budoucnost-programovacich-jazyku - LISP Prolog and Evolution
http://blog.samibadawi.com/2013/05/lisp-prolog-and-evolution.html - List of Lisp-family programming languages
https://en.wikipedia.org/wiki/List_of_Lisp-family_programming_languages - clojure_py na indexu PyPi
https://pypi.python.org/pypi/clojure_py - PyClojure
https://github.com/eigenhombre/PyClojure - Hy na GitHubu
https://github.com/hylang/hy - Hy: The survival guide
https://notes.pault.ag/hy-survival-guide/ - Hy běžící na monitoru terminálu společnosti Symbolics
http://try-hy.appspot.com/ - Welcome to Hy’s documentation!
http://docs.hylang.org/en/stable/ - Hy na PyPi
https://pypi.org/project/hy/#description - Getting Hy on Python
https://lwn.net/Articles/596626/ - Programming Can Be Fun with Hy
https://opensourceforu.com/2014/02/programming-can-fun-hy/ - Přednáška o projektu Hy (pětiminutový lighttalk)
http://blog.pault.ag/day/2013/04/02 - Hy (Wikipedia)
https://en.wikipedia.org/wiki/Hy - GNU Emacs Lisp Reference Manual: Point
https://www.gnu.org/software/emacs/manual/html_node/elisp/Point.html - GNU Emacs Lisp Reference Manual: Narrowing
https://www.gnu.org/software/emacs/manual/html_node/elisp/Narrowing.html - GNU Emacs Lisp Reference Manual: Functions that Create Markers
https://www.gnu.org/software/emacs/manual/html_node/elisp/Creating-Markers.html - GNU Emacs Lisp Reference Manual: Motion
https://www.gnu.org/software/emacs/manual/html_node/elisp/Motion.html#Motion - GNU Emacs Lisp Reference Manual: Basic Char Syntax
https://www.gnu.org/software/emacs/manual/html_node/elisp/Basic-Char-Syntax.html - Elisp: Sequence: List, Array
http://ergoemacs.org/emacs/elisp_list_vs_vector.html - Elisp: Property List
http://ergoemacs.org/emacs/elisp_property_list.html - Elisp: Hash Table
http://ergoemacs.org/emacs/elisp_hash_table.html - Elisp: Association List
http://ergoemacs.org/emacs/elisp_association_list.html - The mapcar Function (An Introduction to Programming in Emacs Lisp)
https://www.gnu.org/software/emacs/manual/html_node/eintr/mapcar.html - Anaphoric macro
https://en.wikipedia.org/wiki/Anaphoric_macro - Some Common Lisp Loop Macro Examples
https://www.youtube.com/watch?v=3yl8o6r_omw - A Guided Tour of Emacs
https://www.gnu.org/software/emacs/tour/ - The Roots of Lisp
http://www.paulgraham.com/rootsoflisp.html - Evil (Emacs Wiki)
https://www.emacswiki.org/emacs/Evil - Evil (na GitHubu)
https://github.com/emacs-evil/evil - Evil (na stránkách repositáře MELPA)
https://melpa.org/#/evil - Evil Mode: How I Switched From VIM to Emacs
https://blog.jakuba.net/2014/06/23/evil-mode-how-to-switch-from-vim-to-emacs.html - GNU Emacs (home page)
https://www.gnu.org/software/emacs/ - GNU Emacs (texteditors.org)
http://texteditors.org/cgi-bin/wiki.pl?GnuEmacs - An Introduction To Using GDB Under Emacs
http://tedlab.mit.edu/~dr/gdbintro.html - An Introduction to Programming in Emacs Lisp
https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html - 27.6 Running Debuggers Under Emacs
https://www.gnu.org/software/emacs/manual/html_node/emacs/Debuggers.html - GdbMode
http://www.emacswiki.org/emacs/GdbMode - Emacs (Wikipedia)
https://en.wikipedia.org/wiki/Emacs - Emacs timeline
http://www.jwz.org/doc/emacs-timeline.html - Emacs Text Editors Family
http://texteditors.org/cgi-bin/wiki.pl?EmacsFamily - Vrapper aneb spojení možností Vimu a Eclipse
https://mojefedora.cz/vrapper-aneb-spojeni-moznosti-vimu-a-eclipse/ - Vrapper aneb spojení možností Vimu a Eclipse (část 2: vyhledávání a nahrazování textu)
https://mojefedora.cz/vrapper-aneb-spojeni-moznosti-vimu-a-eclipse-cast-2-vyhledavani-a-nahrazovani-textu/ - Emacs/Evil-mode – A basic reference to using evil mode in Emacs
http://www.aakarshnair.com/posts/emacs-evil-mode-cheatsheet - From Vim to Emacs+Evil chaotic migration guide
https://juanjoalvarez.net/es/detail/2014/sep/19/vim-emacsevil-chaotic-migration-guide/ - Introduction to evil-mode {video)
https://www.youtube.com/watch?v=PeVQwYUxYEg - EINE (Emacs Wiki)
http://www.emacswiki.org/emacs/EINE - EINE (Texteditors.org)
http://texteditors.org/cgi-bin/wiki.pl?EINE - ZWEI (Emacs Wiki)
http://www.emacswiki.org/emacs/ZWEI - ZWEI (Texteditors.org)
http://texteditors.org/cgi-bin/wiki.pl?ZWEI - Zmacs (Wikipedia)
https://en.wikipedia.org/wiki/Zmacs - Zmacs (Texteditors.org)
http://texteditors.org/cgi-bin/wiki.pl?Zmacs - TecoEmacs (Emacs Wiki)
http://www.emacswiki.org/emacs/TecoEmacs - Micro Emacs
http://www.emacswiki.org/emacs/MicroEmacs - Micro Emacs (Wikipedia)
https://en.wikipedia.org/wiki/MicroEMACS - EmacsHistory
http://www.emacswiki.org/emacs/EmacsHistory - Seznam editorů s ovládáním podobným Emacsu či kompatibilních s příkazy Emacsu
http://www.finseth.com/emacs.html - evil-numbers
https://github.com/cofi/evil-numbers - Debuggery a jejich nadstavby v Linuxu (1.část)
http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu/ - Debuggery a jejich nadstavby v Linuxu (2.část)
http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-2-cast/ - Debuggery a jejich nadstavby v Linuxu (3): Nemiver
http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-3-nemiver/ - Debuggery a jejich nadstavby v Linuxu (4): KDbg
http://fedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-4-kdbg/ - Debuggery a jejich nadstavby v Linuxu (5): ladění aplikací v editorech Emacs a Vim
https://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-5-ladeni-aplikaci-v-editorech-emacs-a-vim/ - Org mode
https://orgmode.org/ - The Org Manual
https://orgmode.org/manual/index.html - Kakoune (modální textový editor)
http://kakoune.org/ - Vim-style keybinding in Emacs/Evil-mode
https://gist.github.com/troyp/6b4c9e1c8670200c04c16036805773d8 - Emacs – jak začít
http://www.abclinuxu.cz/clanky/navody/emacs-jak-zacit - Programovací jazyk LISP a LISP machines
https://www.root.cz/clanky/programovaci-jazyk-lisp-a-lisp-machines/ - Evil-surround
https://github.com/emacs-evil/evil-surround - Spacemacs
http://spacemacs.org/ - Lisp: Common Lisp, Racket, Clojure, Emacs Lisp
http://hyperpolyglot.org/lisp - Common Lisp, Scheme, Clojure, And Elisp Compared
http://irreal.org/blog/?p=725 - Does Elisp Suck?
http://irreal.org/blog/?p=675 - Emacs pro mírně pokročilé (9): Elisp
https://www.root.cz/clanky/emacs-elisp/ - If I want to learn lisp, are emacs and elisp a good choice?
https://www.reddit.com/r/emacs/comments/2m141y/if_i_want_to_learn_lisp_are_emacs_and_elisp_a/ - Clojure(Script) Interactive Development Environment that Rocks!
https://github.com/clojure-emacs/cider - An Introduction to Emacs Lisp
https://harryrschwartz.com/2014/04/08/an-introduction-to-emacs-lisp.html - Emergency Elisp
http://steve-yegge.blogspot.com/2008/01/emergency-elisp.html - Lambda calculus
https://en.wikipedia.org/wiki/Lambda_calculus - John McCarthy's original LISP paper from 1959
https://www.reddit.com/r/programming/comments/17lpz4/john_mccarthys_original_lisp_paper_from_1959/ - Micro Manual LISP
https://www.scribd.com/document/54050141/Micro-Manual-LISP - How Lisp Became God's Own Programming Language
https://twobithistory.org/2018/10/14/lisp.html - History of Lisp
http://jmc.stanford.edu/articles/lisp/lisp.pdf - The Roots of Lisp
http://languagelog.ldc.upenn.edu/myl/llog/jmc.pdf - Racket
https://racket-lang.org/ - The Racket Manifesto
http://felleisen.org/matthias/manifesto/ - MIT replaces Scheme with Python
https://www.johndcook.com/blog/2009/03/26/mit-replaces-scheme-with-python/ - Adventures in Advanced Symbolic Programming
http://groups.csail.mit.edu/mac/users/gjs/6.945/ - Why MIT Switched from Scheme to Python (2009)
https://news.ycombinator.com/item?id=14167453 - Starodávná stránka XLispu
http://www.xlisp.org/ - AutoLISP
https://en.wikipedia.org/wiki/AutoLISP - Seriál PicoLisp: minimalistický a výkonný interpret Lispu
https://www.root.cz/serialy/picolisp-minimalisticky-a-vykonny-interpret-lispu/ - Common Lisp
https://common-lisp.net/ - Getting Going with Common Lisp
https://cliki.net/Getting%20Started - Online Tutorial (Common Lisp)
https://cliki.net/online%20tutorial - Guile Emacs
https://www.emacswiki.org/emacs/GuileEmacs - Guile Emacs History
https://www.emacswiki.org/emacs/GuileEmacsHistory - Guile is a programming language
https://www.gnu.org/software/guile/ - MIT Scheme
http://groups.csail.mit.edu/mac/projects/scheme/ - SIOD: Scheme in One Defun
http://people.delphiforums.com/gjc//siod.html - CommonLispForEmacs
https://www.emacswiki.org/emacs/CommonLispForEmacs - Elisp: print, princ, prin1, format, message
http://ergoemacs.org/emacs/elisp_printing.html - Special Forms in Lisp
http://www.nhplace.com/kent/Papers/Special-Forms.html - Basic Building Blocks in LISP
https://www.tutorialspoint.com/lisp/lisp_basic_syntax.htm - Introduction to LISP – University of Pittsburgh
https://people.cs.pitt.edu/~milos/courses/cs2740/Lectures/LispTutorial.pdf - Why don't people use LISP
https://forums.freebsd.org/threads/why-dont-people-use-lisp.24572/ - Structured program theorem
https://en.wikipedia.org/wiki/Structured_program_theorem - Clojure: API Documentation
https://clojure.org/api/api - Tutorial for the Common Lisp Loop Macro
http://www.ai.sri.com/pkarp/loop.html - Common Lisp's Loop Macro Examples for Beginners
http://www.unixuser.org/~euske/doc/cl/loop.html - A modern list api for Emacs. No 'cl required.
https://github.com/magnars/dash.el - The LOOP Facility
http://www.lispworks.com/documentation/HyperSpec/Body/06_a.htm - Clojure.org: Vars and the Global Environment
http://clojure.org/Vars - Clojure.org: Refs and Transactions
http://clojure.org/Refs - Clojure.org: Atoms
http://clojure.org/Atoms - Clojure.org: Agents as Asynchronous Actions
http://clojure.org/agents - Transient Data Structureshttp://clojure.org/transients
- Dynamic Languages Strike Back
http://steve-yegge.blogspot.cz/2008/05/dynamic-languages-strike-back.html - Scripting: Higher Level Programming for the 21st Century
http://www.tcl.tk/doc/scripting.html - Clojure (na Wikipedia EN)
http://en.wikipedia.org/wiki/Clojure - Clojure (na Wikipedia CS)
http://cs.wikipedia.org/wiki/Clojure - SICP (The Structure and Interpretation of Computer Programs)
http://mitpress.mit.edu/sicp/ - Pure function
http://en.wikipedia.org/wiki/Pure_function - Funkcionální programování
http://cs.wikipedia.org/wiki/Funkcionální_programování - Jazyky Hy a Clojure-py: moderní dialekty LISPu určené pro Python VM
https://www.root.cz/clanky/jazyky-hy-a-clojure-py-moderni-dialekty-lispu-urcene-pro-python-vm/ - Pixie: lehký skriptovací jazyk s „kouzelnými“ schopnostmi
https://www.root.cz/clanky/pixie-lehky-skriptovaci-jazyk-s-kouzelnymi-schopnostmi/ - Programovací jazyk Pixie: funkce ze základní knihovny a použití FFI
https://www.root.cz/clanky/programovaci-jazyk-pixie-funkce-ze-zakladni-knihovny-a-pouziti-ffi/ - Stránka projektu Jython
http://www.jython.org/ - Jython (Wikipedia)
https://en.wikipedia.org/wiki/Jython - Scripting for the Java Platform (Wikipedia)
https://en.wikipedia.org/wiki/Scripting_for_the_Java_Platform - JSR 223: Scripting for the JavaTM Platform
https://jcp.org/en/jsr/detail?id=223 - List of JVM languages
https://en.wikipedia.org/wiki/List_of_JVM_languages - The JavaTM Virtual Machine Specification, Second Edition
http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html - The class File Format
http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html - javap – The Java Class File Disassembler
http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/javap.html - javap-java-1.6.0-openjdk(1) – Linux man page
http://linux.die.net/man/1/javap-java-1.6.0-openjdk - Using javap
http://www.idevelopment.info/data/Programming/java/miscellaneous_java/Using_javap.html - Examine class files with the javap command
http://www.techrepublic.com/article/examine-class-files-with-the-javap-command/5815354 - Economy Size Geek – Interview with Rich Hickey, Creator of Clojure
https://www.linuxjournal.com/article/10708