Tento text je takový malý uživatelský manuálek pro MIT implementaci programovacího jazyka Scheme.
Píše se zde, jak spustit a ukončit MIT Scheme, jak používat REPL, vykonávat v něm příkazy, jak načítat programy Scheme ze souboru, a jak používat při práci editory Edwin a GNU Emacs.
Naopak se zde vůbec nepíše o tom, jak psát procedury a celé programy v jazyce Scheme. Od toho jsou přednášky a cvičení kursu Paradigmata programování.
Tato kapitola popisuje, jak spustit MIT Scheme. Také se zde dozvíte, jak si můžete přizpůsobit chování Scheme k obrazu svému pomocí parametrů příkazového řádku.
Obvykle se Scheme startuje napsáním
scheme
v příkazovém interpreteru operačního systému. Scheme se nahraje, smaže obrazovku, a napíše něco jako:
Scheme saved on Sunday October 18, 1998 at 11:02:46 PM Release 7.4.7 Microcode 11.151 Runtime 14.168
Tento výpis, který může být znovu vypsán vyhodnocením výrazu
(identify-world)
podává různé informace o verzi. Release je číslo verze celého Scheme systému. (alpha) nebo (beta) za tímto číslem značí, že to je alfa- nebo beta-testovací verze. Microcode je verze části systému napsané v C. Runtime je verze části systému napsané ve Scheme.
Můžou následovat další čísla verzí specifických subsystémů. Např. Liar je překladač nativního kódu, Edwin je editor podobný Emacsu.
Můžete si přizpůsobit nastavení použitím těchto utilit:
Scheme akceptuje kromě mnoha jiných parametry popsané v této kapitole. Parametry mohou být zadány v libovolném pořadí, s tím omezením, že parametry mikrokódu musí být uvedeny dříve než runtime parametry.
Parametry mikrokódu:
tato volba je implicitní pro načtení Edwinu |
specifikuje, že Scheme bude běžet jako podproces GNU Emacsu. Tato volba je automaticky používána Emacsem a neměla by být používána |
specifikuje, že Scheme nebude generovat "core" soubor např. při pádu |
Následující parametry jsou runtime parametry. Jsou vykonány po parametrech mikrokódu.
tato volba způsobí ignorování ´~/.scheme.init´ souboru, normálně načítaného, když Scheme startuje |
způsobí, že Scheme vyhodnotí výrazy (nesmí obsahovat znak -) za tímto parametrem až do dalšího parametru začínajícího -. Výrazy jsou vyhodnoceny v user-initial-environment. Chyby při vyhodnocování jsou ignorovány |
způsobí, že Scheme načte soubory (názvy nesmí obsahovat znak -) za tímto parametrem až do dalšího parametru začínajícího -. Soubory jsou načteny do user-initial-environment. Chyby při načítání jsou ignorovány |
Existuje několik způsobů, jak ukončit Scheme: dvě procedury, které můžete zavolat, několik příkazů Edwinu, a tlačítka grafického rozhraní (a jejich klávesové zkratky).
V této kapitole se dozvíte, jak vyhodnocovat výrazy a načítat programy.
Když spustíte Scheme z příkazového řádku (ne v Edwinu, resp. Emacsu), budete psát v programu Read-Eval-Print Loop (REPL). Ten zobrazuje prompt 1 ]=> na levé straně obrazovky kdykoliv čeká na vstup. Napíšete výraz a odešlete ho pomocí RET. Scheme ho vyhodnotí, vypíše výsledek, a zobrazí znova promt (a nejen ho).
REPL prompt má normálně tvar
1 ]=>
Číslo 1 v promptu je číslo úrovně, které je vždy kladné číslo. Toto číslo je inkrementováno za různých okolností, nejčastěji při chybě. Například, tady je to, co uvidíte, když napíšete foo RET po startu Scheme:
;Unbound variable: foo ;To continue, call RESTART with an option number: ; (RESTART 3) => Specify a value to use instead of foo. ; (RESTART 2) => Define foo to a given value. ; (RESTART 1) => Return to read-eval-print level 1. 2 error>
V tomto případě bylo číslo úrovně inkrementováno na 2, což indikuje, že byl spuštěn nový REPL (také prompt se změnil, aby připomínal, že tento REPL byl spuštěn kvůli chybě). 2 znamená nový REPL "nad" tím starým. Originální REPL stále existuje a čeká, až se do něho vrátíte, např. vyhodnocením (restart 1). Dále, když se objeví chyba v tomto REPLu, bude spuštěn další REPL a číslo úrovně se zvýší na 3. Tohle může pokračovat až do nekonečna, ale normálně se používá jen pár úrovní (vypadá to docela blbě, když máte číslo úrovně 52, zatímco kamarád vedle jen 2 :-))
Normálně se z chybového REPLu vrátíte do nejvyššího REPLu použitím C-g. C-g vždy ukončí cokoli běžící a vrátí vás do nejvyššího REPLu okamžitě.
Pozn.: error> prompt neznamená, že je Scheme v nějakém divném nestabilním stavu, kterému byste měli zabránit. Je to jen upomínka, že v programu byla chyba: ilegální operace byla detekována a zrušena. Často nejlepší způsob, jak zjistit, co to bylo za chybu, je trochu se "pohrabat" v chybovém REPLu. Pokud ho zrušíte, všechny informace o chybě budou zničeny a vy už nikdy nebudete schopni žádným způsobem zjistit, co se vlastně stalo (oh, dear ! :-))
Scheme má několik způsobů přerušení. C-g zastaví jakékoli vyhodnocování a vrátí vás do nejvyššího REPLu. C-c se zeptá na další klávesy a pak vykoná akci podle těchto kláves. Za C-g ani za C-c není potřeba RET, ani za tím, co je po C-c.
Přeruší jakékoli vyhodnocování a vrátí vás do nejvyššího REPLu |
Přeruší jakékoli vyhodnocování a vrátí vás do aktuálního REPLu |
Přeruší jakékoli vyhodnocování a vrátí vás do o úroveň vyššího REPLu. Pokud už číslo úrovně je 1, tak přeruší vyhodnocování a zůstane na úrovni 1 |
Suspenduje jakékoli vyhodnocování a spustí breakpoint REPLu. Vyhodnocení může být dokončeno vyhodnocením (continue) kdykoliv v tomto REPLu |
Podobné jako napsání (exit) v REPLu. Funguje i když Scheme něco vyhodnocuje a nepotřebuje potvrzování |
Podobné jako napsání (quit) v REPLu. Funguje i když Scheme něco vyhodnocuje |
Ignoruje přerušení. Použijte, když jste se spletli a nemyslíte to s C-c vážně |
Vypíše nápovědu. Vypíše ještě další volby zde nepopsané |
Další způsob, jak ukončit REPL, je použít proceduru restart:
restart [k] - procedura
Tato procedura vybere a spustí restartovací metodu. Seznam restartovacích metod je jiný pro každý REPL; v případě chybového REPLu je seznam vypsán, když je tento REPL spuštěn:
;Unbound variable: foo ;To continue, call RESTART with an option number: ; (RESTART 3) => Specify a value to use instead of foo. ; (RESTART 2) => Define foo to a given value. ; (RESTART 1) => Return to read-eval-print level 1. 2 error>
Pokud je parametr zadán, musí to být kládný index do listu (v příkladě číslo mezi 1 a 3 včetně). Pokud parametr zadán není, restart vypíše seznam a zeptá se na index:
2 error> (restart) ;Choose an option by number: ; 3: Specify a value to use instead of foo. ; 2: Define foo to a given value. ; 1: Return to read-eval-print level 1. Option number:
Nejjednodušší restartovací metody jen vykonají svůj úkol. Například:
2 error> (restart 1) ;Abort! 1 ]=>
Jiné metody se vás zeptají na další vstup:
2 error> (restart) ;Choose an option by number: ; 3: Specify a value to use instead of foo. ; 2: Define foo to a given value. ; 1: Return to read-eval-print level 1. Option number: 3 Value to use instead of foo: '(a b) ;Value 1: (a b) 1 ]=>
Každý REPL má aktuální prostředí, což je místo, kde jsou vyhodnoceny výrazy a uloženy definice. Když je Scheme nastartován, prostředí je hodnota proměnné user-initial-environment. Existuje spousta dalších prostředí v systému, např. system-global-environment, kde jsou uloženy systémové vazby.
Prostředí aktuálního REPLu můžete získat vyhodnocením výrazu:
(nearest-repl/environment)
POZOR !!! Takto získáte prostředí aktuálního REPLu, ale něco jiného je aktuální prostředí (Proč?! Protože jak všichni dobře víme (nebo budeme vědět - v případě 1. ročníku), prostředí vzniká zavoláním každé funkce a v tomto prostředí je vyhodnoceno tělo té funkce !). Aktuální prostředí získáte vyhodnocením výrazu:
(the-environment)
Jsou různé další způsoby, jak získat prostředí. Například, pokud máte proceduru, můžete získat ukazatel na prostředí, ve kterém byla vyhodnocena:
(procedure-environment procedure)
Tady je procedura, která změní prostředí REPLu:
ge environment - procedura, (ge jako "Goto Environment")
Prostředí aktuálního REPLu bude změněno na prostředí environment. Environment může být i procedura. Potom je použito prostředí, ve kterém byla procedura vyhodnocena.
K načítání souborů s kódem Scheme se používá procedura load:
load jméno_souboru [prostředí] - procedura
Jméno_souboru je jméno souboru nebo seznam jmen souborů. Prostředí je prostředí, ve kterém se soubor vyhodnotí; pokud není zadáno, je použito prostředí aktuálního REPLu.
Je zvykem, že soubory kódu mívají příponu ´.scm´, Scheme soubor s touto příponou implicitně považuje sa soubor se zdrojovým kódem.
Všechny názvy souborů jsou interpretovány relativně k pracovnímu adresáři, který je inicializován, když Scheme startuje. Pracovní adresář lze zjistit zavoláním procedury pwd nebo může být změněn pomocí procedury cd.
Tato kapitola popisuje, jak spustit Edwin, textový editor MIT Scheme. Edwin je velmi podobný editoru GNU Emacs - měli byste se podívat do manuálu GNU Emacsu (nebo si aspoň přečíst kapitolu Prostředí editoru GNU Emacs tohoto manuálku) k získání informací o příkazech a klávesových zkratkách Edwinu - s tím rozdílem, že rozšiřujícím jazykem Edwinu je MIT Scheme, kdežto rozšíření GNU Emacsu jsou napsána v Emacs Lispu. Tato kapitola nepopisuje přizpůsobení Edwinu.
Abyste mohli použít Edwin, spusťte Scheme s parametrem příkazové řádky -edwin, a pak zavolejte proceduru:
edit nebo edwin
A spustí se textový editor Edwin.
Tato procedura se často vyhodnocuje z příkazového řádku, aby se Edwin spustil už při startu Scheme:
scheme -edwin -eval (edit) nebo scheme -edwin -eval (edwin)
Když je Edwin poprvé inicializován, načte si váš inicializační soubor (~/.edwin), jestli ho máte.
Když už byl Edwin spuštěn, může být také ukončen :-) následujícími způsoby:
Zastaví Edwin a vrátí vás do Scheme (suspend-edwin). Ve Scheme to znamená návrat z procedury edit (nebo edwin). Další volání jedné z těchto procedur nastartuje Edwin do toho stavu, ve kterém byl zastaven. |
Nabídne uložení bufferů, zabije :-) Edwin a vrátí vás do Scheme (save-buffers-kill-edwin). Je to jako předchozí příkaz s tím rozdílem, že další volání jedné z procedur edit nebo edwin nastartuje a reinicializuje Edwin. |
Zastaví Edwin, suspenduje Scheme a vrátí řízení příkazovému interpreteru operačního systému (suspend-scheme). Když se vrátíte do Scheme (pomocí úkoly ovládajících příkazů interpreteru (fg, bg, ...)), restartuje se Edwin do toho stavu, ve kterém byl zastaven. Tento příkaz je stejný jako C-x C-z v GNU Emacsu. |
Nabídne uložení bufferů, zabije :-) Edwin i Scheme (save-buffers-kill-scheme). Řízení je navráceno příkazovému interpreteru operačního systému, a proces Scheme je ukončen. Tento příkaz je stejný jako C-x C-c v GNU Emacsu. |
Scheme je možné provozovat jako podproces Emacsu.
Toto prostředí je podporováno jen pod Unixem. (Nevím o něčem podobném takovému mocnému nástroji jako je GNU Emacs pod jiným operačním systémem !)
(Ehm. Existuje port GNU Emacsu (a jinych GNU veci) pod M$ OS. Sam pouzivam Jed for Window, abych se nemusel ucit jine ovladani - chicky)Ke spuštění Scheme z Emacsu použijte M-x run-scheme. GNU Emacs automaticky použije parametr příkazové řádky -emacs.
Scheme bude spuštěn jako podproces v bufferu *scheme*. Tento buffer bude ve scheme-interaction-mode a všechen výstup ze Scheme procesu půjdu sem. Řádka módu pro buffer *scheme* bude mít tento tvar:
_**-*scheme*: 1 [Evaluator] (Scheme Interaction: input)------
První pole, 1 v tomto příkladu, je číslo úrovně. Druhé pole, [Evaluator] v tomto příkladě, je typ REPLu, který běží. Jiná hodnota je např. [Debugger]
Mód po Scheme Interaction je jeden z:
input - Scheme čeká na vstup
run - Scheme vyhodnocuje výraz
gc - Scheme "sbírá smetí"
Takhle máme "obyčejný" Scheme, pod Emacsem, což je sice hezké, ale na tohle není Emacs potřeba. Proto existuje ještě scheme-mode, což je obyčejný textový editační mód. Tento mód se spustí buď otevřením souboru s příponou ´.scm´ nebo příkazem M-x scheme-mode.
Ale pozor, tento mód není úplně obyčejný. V tomto módu máme k dispozici různé příkazy na vyhodnocení výrazů:
Vyhodnotí aktuální buffer (xscheme-send-buffer) |
Vyhodnotí aktuální definici (xscheme-send-definition) |
Vyhodnotí výraz nalevo od kurzoru (xscheme-send-previous-expression) |
Vybere *scheme* buffer a nastaví kurzor na jeho konec (xscheme-select-process-buffer) |
Následující příkazy poskytují možnost přerušení:
Přeruší jakékoli vyhodnocování a vrátí vás do nejvyššího REPLu (xscheme-send-control-g-interrupt) |
Přeruší jakékoli vyhodnocování a vrátí vás do aktuálního REPLu (xscheme-send-control-x-interrupt) |
Přeruší jakékoli vyhodnocování a vrátí vás do o úroveň vyššího REPLu. Pokud už číslo úrovně je 1, tak přeruší vyhodnocování a zůstane na úrovni 1 (xscheme-send-control-u-interrupt) |
Jako vyhodnocení (proceed) nebo (continue) (xscheme-send-proceed) |
A co z toho? No, to je úplně jednoduché:
No a teď můžeme vesele psát kód programu nebo výrazu (kopírovat, přesouvat, mazat text), a až ho napíšeme správně, tak si jej vyhodnotíme "do" druhého okna s "čistým" Scheme, kde vidíme také výsledek vyhodnocení. Výrazy k vyhodnocení můžeme samozřejmě psát a vyhodnocovat také v okně s tímto "čistým" Scheme.
Až skončíme s prací ve Scheme, uložíme si soubor s kódem programu (pomocí C-x C-s), můžeme ukončit Scheme v druhém bufferu např. zavřením bufferu (pomocí C-x k), a případně i ukončit Emacs (pomocí C-x C-c).
A to je vše. Přeji vám příjemnou a bezproblémovou práci s MIT Scheme !