Dnes se podíváme na léty prověřený funkcionální jazyk LISP (List processing). Protože ne každému je pojem funkcionální jazyk známý a v dalším dílu se ještě s některými jazyky z této široké skupiny setkáme, pojďme si nejprve pojem funkcionální jazyk trochu přiblížit a správně zařadit.
Obecně se programovací jazyky dělí na imperativní (procedurální) a deklarativní (neprocedurální). Většina jazyků, které jsou v současné době širokou veřejností běžně používány, jsou jazyky imperativní. V principu je základem těchto jazyků algoritmus. Tedy postup vyjádřený přesnou posloupností příkazů, jak se má daná úloha vyřešit. V minulých dílech popisované jazyky byly imperativní.
U deklarativních jazyků je řešená úloha popisována prostřednictvím funkcí, nebo logických výrazů. Podle toho, pomocí čeho je daná úloha popsána, dělíme deklarativní jazyky dále na jazyky funkcionální (LISP, Haskell, Scheme, …), které k popisu úlohy využívají funkcí a relační (Prolog), které k popisu úlohy využívají logických výrazů. Nyní však již přejděme k samotnému LISPu.
Duchovním otcem jazyka LISP je John McCarthy, který ho v roce 1958 ve svých 31 letech navrhl při svém působení na MIT (Massachusetts Institute of Technology). Počátečním záměrem nebyla snaha vytvořit nový programovací jazyk, ale pouze rozšířit v té době velmi populární jazyk FORTRAN o zpracovaní seznamů (List processing). V roce 1960 pak byl LISP představen široké odborné veřejnosti článkem „Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I“ (druhá část nebyla nikdy publikována) v časopise „Communications of the ACM“.
Implementaci LISPu provedl Steve Russel na tranzistorovém počítači IBM 704. První překladač LISPu vytvořili Tim Hart a Mike Levin. Celý překladač byl napsán v LISPu.
Již od svého počátku se LISP používal především k účelům výzkumu umělé inteligence. Toto použití samozřejmě vedlo k vysokým požadavkům na hardware a tak v 70. letech byly vyvinuty speciální LISPové procesory (LISP machine) uzpůsobené k běhu rozsáhlých LISPovských aplikací.
Během několika dalších let existence LISPu vzniklo mnoho různých LISPovských dialektů, a tak byla snaha po sjednocení do jednoho jazyka. Tímto jazykem se nakonec stal Common Lisp, který byl v roce 1994 standardizován organizací ANSI. Důležité však je, že od 60. let zůstaly základní principy jazyka LISP v podstatě nezměněné.
LISP je jazyk interpretovaný a práce s interpretrem probíhá ve čtyřech fázích (zkráceně REPL): Read (načtení příkazu), eval (vyhodnocení), print (vypsání výsledku) a loop (znovu na začátek).
Data i kód se reprezentují stejně. Seznam (A B C D) může znamenat seznam čtyř prvků A,B,C,D (interpretuje se jako data) a nebo funkci A se třemi parametry B,C,D (interpretuje se jako kód). LISP užívá dva rozdílné datové typy, kterými jsou symboly (atoms) a seznamy symbolů (lists). Symbolem může být identifikátor, nebo konstanta. Seznamem pak jsou seznamy symbolů a nebo kombinace seznamů a symbolů. Dalšími rysy LISPu je silné užívání rekurze a existence garbage coollection.
Jak je vidět i z našich dvou příkladů, první, čeho si na LISPu všimnete, je až přespříliš závorek. Díky tomuto se s humorem zkratka LISP vysvětluje nejenom jako List processing, ale také Lots of Insanely Stupid Parentheses, Lots of Irritating Superfluous Parentheses, Lots of Infuriating and Silly Parentheses, nebo Lots of Isolated Silly Parentheses.
Pro představu programu napsaného v LISPu si jako tradičně uvedeme program Hello World a dále pak jednoduchý program na převod kilometrů na míle.
Ukázka programu Hello, World!:
Ukázka programu Hello, World!:
(DEFUN HELLO ()
"HELLO WORLD"
)
Ukázka programu pro převod kilometrů na míle:
(defun convert ()
(format t "Zadej pocet kilometru: ")
(LET (kilometr)
(SETQ kilometr (read kilometr))
(APPEND '(je v milich) (/ kilometr 1.609))
)
)
LISP i v dnešních dnech dominuje v oblasti umělé inteligence. Především se používá k vytváření umělé inteligence robotů, rozeznávání vzorů či psaní logických počítačových her. LISP je taktéž vhodný jako vnitřní programovací jazyk (embedded) různých aplikací. Příkladem toho je například AutoCAD (Autolisp), editor EMACS (Emacs Lisp), nebo legendární hra Abuse.
Odkazy:
RECURSIVE FUNCTIONS OF SYMBOLIC EXPRESSIONS AND THEIR COMPUTATION BY MACHINE (Part I)
Zpráva o prvním LISP překladači
Informace a odkazy týkající se LISPu
Článek vyšel původně v časopisu LinuxEXPRES. Autor článku Lukáš Faltýnek.
Článek je uveřejněn s GNU FDL licencí (anglicky).
Tedy vím, že se jedná o starší článek, ale přeci jen bych měl dvě poznámky.
1) V článku byl Lisp představen jako (pouze) funkcionální jazyk, ale Lisp obsahuje i další paradigmata. Obecně řečeno lze v Lispu programovat jakkoliv, a když ne, tak to jde pomocí maker doprogramovat 8-). Každopádně můžeme v Lispu klidně programovat procedurálně či objektově (CLOS).
2) Ty výpisy kódů… To je hrůza :-). LISP není Céčkový jazyk a proto nemůžeš přebírat Céčkové zápisy kódů. Ty uzavírací závorky nepatří na zvláštní řádek jako v Céčku, ale patří na konec posledního řádku. Tedy tvá funkce dle zvyklostí LISPu:
(defun convert ()
(format t „Zadej pocet kilometru: „)
(LET (kilometr)
(SETQ kilometr (read kilometr))
(APPEND ‚(je v milich) (/ kilometr 1.609))))
A teď ještě k té funkci, začnu od konce: Poslední append nemá moc smysl, protože append slouží ke sloučení seznamů. Ty jej používáš na sloučení seznamu ‚(je v milich) a ČÍSLA (/ kilometr 1.609). Výsledek může vypadat takto: (JE V MILICH . 6.2150407). To je poměrně zvláštní výsledek. Správně by ta funkce měla vracet buď jen počet mil (tzn. vrcela by pouze číslo) nebo pokud se jedná pouze o informativní výpis uživateli, měl by výpis probíhat zase přes (format t …). Takže správně by ta funkce měla vypadat takto:
(defun convert ()
(format t „Zadej pocet kilometru: „)
(let ((kilometr (read)))
(format t „~s kilometru je v milich ~s“ kilometr (/ kilometr 1.609))))
Výsledek by pak vypadal: 10 kilometru je v milich 6.2150407.
Hned jsem tam opravil i druhou chybu. Je zbytečné vytvářet v letu nenavázaný symbol a následně na něj pomocí setq něco navazovat. To přece můžeme udělat přímo v tom letu, tedy můžeme použít toto: (let ((kilometr (read))).
Každopádně úplně ideální by bylo, kdyby ta funkce vypadala jenom takhle:
(defun km2miles (km)
(/ km 1.609))
Byla by nejvíce použitelná 8-).
Když tak u sebe mám pár článků o Lispu, třeba tě to bude zajímat :-). http://itblob.havrlant.net/kategorie/Lisp/