Začátky v LISPu (10.12. 2008)
Dnes si řekneme co to vlastně Common LISP je (po mynulém článku, kdy jsme si vysvětlili jak je LISP skvělý), pokusíme se sžít s jeho syntaxí (pro některé to může být ze začátku těžké, ale časem zjistíte, že je přirozenější než syntaxe většiny ostatních jazyků) a prozradíme si, kde zdarma legálně stáhnout vývojové prostředí.
Co je to vlastně LISP?
Zkratka znamená List processing neboli zpracování seznamů a velmi jednoduše popisuje jakým způsobem vlastně celý programovací jazyk pracuje.
Interpret LISPu totiž postupně bere a vyhodnocuje seznamy výrazů (takzvané s-výrazy). Zjednodušeně při tom postupuje podle následujícího schématu:
- Pokud je zpracováván elementární prvek, vrátí jeho hodnotu (u čísel číslo, u symbolů jejich vazbu)
- Pokud je zpracovávaný prvek seznam:
- Zpracuje první prvek seznamu (zde očekává funkci, makro nebo speciální funkci)
- Zpracuje v nespecifikovaném pořadí ostatní prvky seznamu (u některých speciálních funkcí nebo maker nemusí zpracovat všechny, u obyčejných funkcí ano)
- Vrátí jako hodnotu hodnotu vrácenou funkcí (makrem, speciální funkcí ...)
- Takto cyklus postupně vyhodnotí veškeré výrazy předané na vstup
Ve skutečnosti je proces o něco složitější a existují různé výjimky či dolňující pravidla těmi se však nebudeme nyní zabývat. Stačí si uvědomit, že LISP bere postupně jednotlivé prvky seznamu a vyhodnocuje je, přičemž vnořené seznamy mu nevadí, ba dokonce jsou žádoucí a nutné.
Kde sehnat vývojové prostředí a jak s ním pracovat?
Abychom se vyhnuli zbytečnému dělení ukázkového kódu na několik větví podle interpretu LISPu (těch vyhovujících standardu je několik), budeme pužívat interpret LispWorks, který je dle mého jedním z nejlepších a navíc je volně šiřitelný ve verzi pro Windows, Linux, Macintosh i FreeBSD.
Volně šiřitelná verze je zdarma a ačkoliv se po 5ti hodinách zavře, není problém ji znova otevřít (potřebu ukládat rozpracovaný kód snad připomínat nemusím a je samozřejmostí), chybí mu sice funkce save-image, a load-all-patches ale ty se dají obejít a nejsou nutné pro hladký chod LISPu. Trošku horší je to pokud chcete pracovat s knihovnami, které stáhnete nebo vytvoříte. Ty si budete muset v personal(zdarma) verzi inicializovat sami. Nic vám ale nebrání si zkompilovat jeden soubor který všechny potřebné nainicializuje za vás a pak to znamená tři kliknutí po spuštění LispWorks.
Volně šiřitelnou verzi si můžete stáhnout na adrese http://www.lispworks.com/downloads/ po stažení LISPworks jej nainstalujete a už můžete nedočkavě spouštět ono vývojové prostředí.
Po spuštění se vám ihned spustí okno Listeneru – konzole ve které můžete vyhodnocovat s-výrazy (kód a/nebo data). V něm budeme velmi dlouhou dobu spouštět a testovat všechny napsané programy.
Systémové menu file, edit, tools ... snad nemusím vysvětlovat.
Z ikonek nás bude zajímat zatím jen Listener
a Editor
(případně output-browser
)
Mohli vrhnout přímo do víru programování. Jelikož je ale LISP něco docela jiného než jsme zvyklí, neuškodí nejprve trocha procvičování (učení se) syntaxe.
Jak ti chytřejší z vás již podle popisu vyhodnocování seznamů pochopili, LISP bude pracovat se seznamy (a bude mu jedno, jestli znamenají data nebo program. Tak jako takje nakonec převede na elementární prvky a ty potom vyhodnotí)
Uvedu tedy jednoduchý příklad s aritmetickými operacemi (zatím si jednotlivé příkazy zkoušejte v listeneru, kde na vás po odentrování rovnou vyskočí výsledek).
- (+ 1 2)
- ; => 3
- (+ 1
- (+ 2 3))
- ; => 6
- (+ 1 2 3)
- ; => 6
- (/ (+ 20 (* 2 2))
- (- 10 2))
- ; => 3
V prvním řádku aplikujeme sčítání na 1 a 2. (infixově 1 + 2) Výsledek 3 tady nejspíše nikoho nepřekvapí.
Na třetím a čtvrtém řádku podlehneme infixovému neduhu a příklad (1 + 2 + 3) přepíšeme jako (+ 1 (+ 2 3)) pro větší přehlednost si odřádkujeme, ale i u takto jednoduchého příkladu to nevypadá hezky.
Lisp má totiž spoustu funkcí definovaných pro libovolný počet argumentů (narozdíl od silně typovaných jazyků) a proto si může dovolit luxus a tento jednoduchý příklad zapsat jako (+ 1 2 3) (viz řádek 6) kdy se operace plus aplikuje na všechny argumenty seznamu (jelikož je plus komutativní a asociativní, nikdy nám to nebude vadit)
Na řádku 7 jsem pak rozepsal (20+2*2)/(10-2).
Doporučuji vyzkoušet si přepsat několik komplikovanějších matematických výrazů, abyste přišli prefixové notaci na chuť nicméně není na tom opravdu nic složitého nebo nepřirozeného (spíš si uvědomme, že čteme zleva doprava takže je vlastně přirozenější psát co se bude dít a potom s čím.)
Když jsme si vyzkoušeli syntax jazyka, jsme již připraveni začít vytvářet naše první funkce. Vytvořme si tedy funkci na počítání druhé mocniny a poté třeba funkci na hledání nejmenšího ze dvou a tří argumentů.
- (defun na-druhou (x)
- (* x x))
- ;(na-druhou 3) => 9 (na-druhou 4) => 16 ...
- (defun min-2 (a b)
- (if (< a b)
- a
- b))
- ;(min-2 1 2) => 1 (min-2 2 1) => 1
- (defun min-3 (a b c)
- (min-2
- (min-2 a b)
- (min-2 b c)))
- ;(min-3 1 2 3) => 1 (min-3 2 1 3) => 1 (min-3 3 2 1) => 1
Nyní si rozeberme kód.
Předně jsme zjistili, jak definovat funkce – pomocí makra defun.
Syntaxe makra defun je:
(defun <název-funkce> <seznam-parametrů-funkce> <tělo-funkce>)
K tomuto makru se vrátíme ještě v dalším díle kde se budeme seznamovat s prostředími. Zatím nám stačí vědět, že když pomocí defun nadefinujeme funkci, budeme ji moci volat tak, že vytvoříme seznam na jehož prvním místě bude název funkce a na dalších postupně argumenty (zatím vytváříme funkce s pevným počtem argumentů) funkce poté provede kód a vrátí výsledek posledního výrazu (zatímjsme měli funkce jejihž tělo bylo tvořeno pouze jediným výrazem, nicméně do budoucna se to bude hodit)
za komentářem (středník do konce řádku) jsem uvedl vždy nkolik ukázek použití přičemž vždy dodržuji zásadu výraz => vyhodnocení výrazu.
První funkce tedy vrací pouze x násobeno samo sebou, což je přesně to, co bychom od funkce na-druhou očekávali. Krátké, jednoduché a efektivní.
V další funkci již používáme speciální operátor if Ten má syntaxi:
(if <podmínka> <větev-true> <nepoviná-větev-false>)
Přičemž otestuje podmínku. Běžně se používají predikáty > < >= <= = <>, ale za podmínku můžeme brát v podstatě libovolný výraz, přičemž jakákoliv hodnota jiná než nil (což je buďto nepravda nebo prázdný seznam) se vyhodnotí jako t (pravda, true).
Pokud je podmíka splněna (není nil), vyhodnotí se první větev, jinak se vyhodnotí druhá větev.
Zajímavé a užitečné je, že jelikož je LISP interpretovaný jazyk a if je speciální operátor, program se o zamítnuté větvi nikdy nedozví, že existovala (kód se nezkompiluje ani neinterpretuje). Pokud by byl if funkce a nikoliv speciální operátor, nejprve by se vyhodnotily všechny prvky seznamu (tedy obě větve) a poté se vybrala jedna z nich, která se vybere. Toto je nicméně pouze zajímavost a nebudeme se tím nijak znepokojovat.
U třetí funkce min-3, která vrací minimum ze tří prvků jsme již nevyužili žádnou novou funkci či operátor. Zajímavý je nicméně funkcionální přístup, kdy ve funkci, která má dělat něco většího použijeme již hotovou fungující funkci, obstarávající část úkonu. Namísto abychom psali hromadu ifů (tak by nepochybně postupovala většina nepřílišdobrých či průměrných Cčkařů), využijeme faktu, že porovnáním dvou čísel získáme jedno číslo a takto tedy získáme ze tří dvě a ze dvou jedno.
Tak tedy máme v editoru napsaný kód, rozumíme mu (doufám, protože je opravdu velmi jednoduchý), zbývá nám jej již jen spustit a otestovat.
K tomu slouží ikonky Compile Buffer a Compile Deffinition
(první kompiluje celý kód, druhá pouze definici na které se nalézá kurzor)
Jakmile kompilace proběhne v pořádku, přepneme si na listener a můžeme vyzkoušet své fnunkce (příklady jsem zakomentoval přímo do kódu takže stačí zkopírovat například (min-2 1 2) a listener už vám hrdě hlásí 1.
V příštím článku už začneme být odvážní a řekneme si, co jsou to prostředí, jak se navazují symboly a ukážeme si nějaký praktičtější příklad.
Komentáře k článku
Nebojte se napsat, že se vám článek líbil, nebo nelíbil a proč. Rád si přečtu i váš názor ;)
Systém podporuje Gravatary. Email je nutné vyplnit, avšak nezobrazí se.
Drobek
19.04. 2009 06:19
www stránky: http://drobek.nadrobeny.net
Ano ... někdy...
Sir Kubiq
16.04. 2009 23:57
www stránky: http://www.kubiq.notedown.cz
Ahoj, hodláš tedy někdy přidat ten další příspěvek jak už nějakou dobu slibuješ? :-D
Drobek
15.12. 2008 20:38
www stránky: http://drobek.nadrobeny.net
Ale notak tohle má být pro začátečníky. Příště prostředí, pak až vtipné funkce, rekurze a iterace.
Fafrin
15.12. 2008 16:34
Drobek: btw - čímž se dostáváme k foldru
Drobek
14.12. 2008 14:45
www stránky: http://drobek.nadrobeny.net
Hehe. Nojo. Ale myslím že dostál by na takové drobnosti nevyhazoval pokud je to písemné a napíeš místo define defun tak pohoda. Pokud to je na počítači, zjistíš, že tonefunguje a že nezná defun tak to přepíšeš ;)
btw: Vojta Pikal mě správně upozornil, že v příkladu funkce min-3 mám jedno zbytečné volání min-2. Efektivnější kód by tedy vypadal takto:
- (defun min-3 (a b c)
- (min-2 (min-2 a b) c))
nat
14.12. 2008 14:25
www stránky: http://notedown.cz
Kruci! Já se učím na zkoušku ze Scheme a ty na mě vybafneš s Lispem... se vsadím že tam Dostalovi napíšu místo define defun!
BKŮV 

