Movatterモバイル変換


[0]ホーム

URL:


Přeskočit na obsah
WikipedieWikipedie: Otevřená encyklopedie
Hledání

Lisp

Z Wikipedie, otevřené encyklopedie

Lisp (historickyLISP) je rodina multiparadigmatickýchprogramovacích jazyků s dlouhou historií. Jeho název je zkratka proListprocessing (zpracování seznamů). Přestože se jedná spíše o akademický jazyk, používá se i na reálných projektech, např. v oboruumělé inteligence. Používá ho také napříkladtextový editorEmacs či konstrukční programAutoCAD.

Lisp byl původně specifikován v roce 1958. V současné době se jedná o druhý nejstarší vysokoúrovňový jazyk, který se stále ještě používá v praxi; starší už je pouzeFortran. Lisp byl původně navržen jako programovací jazyk pro matematické výpočty a byl silně ovlivněn syntaxíLambda kalkulu. Rychle se stal favorizovaným programovacím jazykem ve světěumělé inteligence. Lisp se stal průkopníkem v mnoha programových technikách, například:stromové struktury,automatická správa paměti nebo dynamické typování. Lisp nevnímá rozdíl mezi kódem a daty, díky čemuž má jednoduchou syntaxi. Celý program je tak složen z s-výrazů nebo ozávorkovaných seznamů ve tvaru(f a b c), kde na prvním místě je operátor/funkce a na dalších argumenty funkce. Všechny další funkce jazyka mají identickou syntaxi.

Z Lispu jsou odvozeny i další jazyky – napříkladTcl,Smalltalk neboScheme. Tvůrcem jazyka bylJohn McCarthy.

Syntaxe

[editovat |editovat zdroj]

Základním zápisem v Lispu je seznam. Zapisuje se tímto způsobem:

(12"ahoj"13.2)

Tento seznam obsahuje čtyři prvky:

  • celé číslo 1
  • celé číslo 2
  • řetězec znaků „ahoj“
  • reálné číslo 13,2

Seznam v příkladu reprezentuje uspořádanou čtveřici. Závorky v jazyce Lisp nefungují tak jako vmatematice, ale pouze označují začátek a konec seznamu.

Seznamy jsou v Lispu implementovány jakobinární strom degenerovaný na jednosměrnýspojový seznam.

Co se seznamem Lisp udělá, záleží na okolnostech.

Příkazy

[editovat |editovat zdroj]

Příkazy jazyka Lisp se zapisují také jako seznam, jehož první prvek seznamu je název příkazu.

Například sčítání je realizováno příkazem+. Odpovídající konstrukce v jazyce vypadá takto:

(+123)

Interpret odpoví6.

Ukázka kódu

[editovat |editovat zdroj]

Programhello world lze zapsat několika způsoby. Nejjednodušší vypadá takto:

(formatt"Hello, World!")

Funkce se v Lispu definují klíčovým slovemdefun:

(defunhello()(formatt"~&Hello, World!~%"))(hello)

Na prvních dvou řádcích je definice funkcehello, na třetím řádku je tato funkce svým jménem zavolána.

Funkcím lze předávat i argumenty. V následujícím příkladu je ukázka funkcefact, která vypočítáfaktoriál zadaného čísla:

(defunfact(n)(if(zeropn)1(*n(fact(-n1)))))

Pro výpočet faktoriálu čísla 6 předáme tuto hodnotu jako argument funkci fact:

(fact6)

Návratovou hodnotou funkce bude hodnota 720.

Makra

[editovat |editovat zdroj]

Lisp má jako jeden z mála jazyků propracovaný systém maker, díky kterým lze velmi výrazným způsobem ovlivnit celý jazyk. Makra jsou nejprve načtena v READ části REPLu, následně je provedena makroexpanze (tu provádí preprocesor) a až poté je celý výraz vyhodnocen běžnou EVAL částí. Nemá smysl uvažovat o aplikaci makra, v době vyhodnocení výrazu již žádné makro neexistuje. Makro pouze přepisuje text/kód předtím, než se předhodí k vlastnímu vyhodnocení. Zásadní rozdíl mezi makrem a funkcí pak je, že makro nevyhodnocuje své argumenty při zavolání funkce.

Quote, Unquote, Quasiquote

[editovat |editovat zdroj]

Abychom mohli makra vůbec používat, musíme mít nějaké nástroje k transformaci kódu. Běžně se používá speciální operátorquote, který vrátí následný výraz tak jak mu ho předáme — žádnou část nevyhodnotí. Jako syntaktickou zkratku můžeme použít apostrof'.

;; Mohlo by se zdát, že quote není potřebný operátor, když máme list,;; ale jak je vidět, je mezi nimi zásadní rozdíl — funkce list vyhodnocuje;; všechny své argumenty, quote nevyhodnotí nic.>(quote(123))(123)>(list123)(123)>(quote(1(+234)5))(1(+234)5)>(list1(+234)5)(195)>(quote(abcd))(ABCD)>(listabcd)Error:ThevariableAisunbound.>'(123)(123)

Abychom mohli i kvotované části nechat něco vyhodnotit, musíme mít mechanismus, kterým zrušíme ono kvotování a vrátíme se zpět k vyhodnocování. K tomu slouží speciální operátoryunquote aquasiquote. Quasiquote se chová stejně jako quote, pouze s tím rozdílem, že ve svém těle umožňuje použít unquote, který vyhodnotí daný výraz. Syntaktická zkratka pro unquote je čárka, a pro quasiquote zpětný apostrof`.

>`(12,(+34))(127)>`(list12,(list34))(LIST12(34))>`('a'b,(list(+12)(+34))cd)((QUOTEA)(QUOTEB)(37)CD)

Základní práce s makry

[editovat |editovat zdroj]

Makra se vytvářejí pomocí speciálního operátorudefmacro. Nejjednodušší příklad může být definice vlastní podmínky, vlastního ifu. Pomocí makra by to vypadalo následovně:

(defmacromy-if(condtruefalse)`(if,cond,true,false))

Makro se chová stejně jako běžný if:

>(my-if123)2;; Makro vrátí dvě jedničky, protože jednou se vytiskne;; a jednou se vrátí jako výsledek funkce print.>(my-if1(print1)(print2))11>(my-ifnil(print1)(print2))22

Při definici „vlastního“ ifu musíme použít makro, protože nevyhodnocuje své argumenty. Kdybychom nadefinovali if jako funkci, nechovalo by se to stejně, protože argumenty už by se vyhodnotily při volání funkce a tím pádem by se vždy vyhodnotily obě větve podmínky.

(defunmy-bad-if(condtruefalse)(ifcondtruefalse));; Příklady volání:;; Zde proběhne vyhodnocení správně>(my-bad-if123)2;; Při tomto volání se chybně vytiskne jedna šestka>(my-bad-if1(print5)(print6))565

Problémy spojené s makry

[editovat |editovat zdroj]

Při používání maker si musíme dávat pozor na dva klasické problémy –dvojí vyhodnocení asymbol capture. Představme si if, který v true větvi automaticky vrátí výsledek podmínky a ve false větvi vrátí předaný argument. Ukázka, jak by to mělo fungovat:

; 1 je true, tak vrátí 1>(if-false12)1; Výsledný seznam je true, vrátí seznam>(if-false(member2'(12345))'nic)(2345); nil je false, vrátí symbol nic>(if-false(membernil'(12345))'nic)NIC

Naivní implementace by mohla vypadat takto:

(defmacroif-false-1(condfalse)`(if,cond,cond,false))

Toto makro zdánlivě funguje. Ovšem do doby, než na něj pustíme kód s vedlejším efektem:

;; Funguje jak má>(if-false-1(member2'(12345))'nic)(2345);; Funguje jak má>(if-false-1(membernil'(12345))'nic)NIC;; Makro incf zvyšuje hodnotu symbolu o jedna.;; Nefunguje jak má — očekáváme, že volání vrátí dvojku.>(let((a1))(if-false-1(incfa)'nic))3

Kód(incf a) se v těle makra vyhodnotil dvakrát, proto nám to vrátí trojku. Kód po makroexpanzi vypadá takto:

(LET((A1))(IF(INCFA)(INCFA)'NIC))

Řešením je navázat vyhodnocenou podmínku na nějaký symbol:

(defmacroif-false-2(condfalse)`(let((cond-help,cond))(ifcond-helpcond-help,false)))

Teď už se výraz vyhodnotí pouze jednou:

>(let((a1))(if-false-2(incfa)'nic))2

Externí odkazy

[editovat |editovat zdroj]
Programovací jazyky
abecední seznam programovacích jazyků
multiparadigmatické

AdaC++Common LispDF#GoOberonPerlPHPPythonRakuRubyRustScalaSwiftTcl (Tk) •Vala

strukturované (procedurální)

AWKCCOBOLDCLForthFortranLuaModula-2 /Modula-3PascalPawnPL/SQL

objektové
funkcionální
dotazovací

LINQSPARQLSQLXQueryXSL (XSLTXSL-FOXPath)

logické
výukové
ezoterické
historické

ALGOLAPLBBASICCPL (BCPL) •JMUMPSPL/ISimula 67SNOBOL

další
skriptovací/strojový kódkompilované/interpretovanéinteraktivní/dávkovéWYSIWYG
Autoritní dataEditovat na Wikidatech
Citováno z „https://cs.wikipedia.org/w/index.php?title=Lisp&oldid=19229412
Kategorie:
Skryté kategorie:

[8]ページ先頭

©2009-2026 Movatter.jp