A Common Lisp a Lisp programozási nyelv egyik dialektusa, amit az "ANSI INCITS 226-1994 (R2004), (korábban X3.226-1994 (R1999))" szabványban publikáltak.Quoted from cover of cited standard. ANSI INCITS 226-1994 (R2004), for sale on standard's document page . Ebből az ANSI Common Lispből származik a Common Lisp HyperSpec webes használatra.Authorship of the Common Lisp HyperSpec A Lisp szabványosításának érdekében alkották meg, hogy összefogja a különböző, főként a MacLisp variánsokat, ezért sokkal inkább specifikáció, mint megvalósítás. Léteznek szabad és kereskedelmi implementációi is.
A Common Lisp általános célú multiparadigmás nyelv, ami támogatja a funkcionális, a procedurális és az objektumorientált paradigmákat. Dinamikus tulajdonsága és az iteratív fordítás lehetősége segíti az inkrementális és evolúciós fejlesztést.
Támogatja az opcionális típusannotációkat és a konverziókat, amelyek szükség szerint hozzávehetők a profilozó és az optimalizációs fázisokban. Például a fixnum tartalmazhat egy egész számot a hardver és az implementáció által támogatott tartományban, amitől hatékonyabbá válnak a nagy számokon vagy a tetszőleges pontosságú számokon végzett műveletek. Hasonlóan, a fordítóval optimize deklarációkkal modulonként és függvényenként közölhető az alkalmazott biztonsági szint.
A Common Lisp tartalmazza a CLOSt, egy objektumrendszert, ami támogatja a multimetódusokat és a metódusok kombinálását. A nyelv bővítésére erős eszközt adnak a makrók, amelyekkel a program fordítási időben átírhatja magát, és a C makrókhoz hasonlóan működő olvasó makrók, amelyek speciális jelentést adnak egyes karaktersorozatoknak.
Habár a Common Lisp nem annyira népszerű, mint egyes nem Lisp nyelvek, több eszközét átvették más, népszerűbb nyelvek.
Szintaxis A Common Lisp egy Lisp nyelvjárás; S-kifejezéseket (azaz beágyazott listákat) használ mind az adatok, mind a rajtuk végzett műveletek leírására. A függvény- és a makróhívásokat listába kell tenni, ahogy a következő példák mutatják:
(+ 2 2) ; összeadja a 2-t és a 2-t, az eredmény 4. (defvar *x*) ; Kimondja, hogy *x* létezik, ; értékadás nélkül. A csillagok is a névhez tartoznak. ; Innen kezdve az *x* következő kötései dinamikusak, ; és nem lexikálisak. (setf *x* 42.1) ; az *x* értéke a 42.1 lebegőpontos szám ;; Egy négyzetre emelő függvény definíciója: (defun square (x) (* x x)) ;; a függvény végrehajtása: (square 3) ; 9 ;; a 'let' szerkezet hatókört vezet be a lokális változók számára. ;; Itt az 'a' változóhoz a 6, és a 'b' változóhoz a 4 értéket kapcsoljuk. ;; A 'let' belseje a 'let' törzse, ami az utoljára kiszámított értéket adja vissza. ;; Itt az eredmény a és b összege, ezt adja vissza a 'let' kifejezés. ;; Az a és b változók hatóköre lexikális, kivéve ha ;; speciális változónak deklaráltuk őket (például egy korábbi DEFVARral). (let ((a 6) (b 4)) (+ a b)) ; returns 10
Adattípusok A Common Lispben sok adattípus van; több, mint más nyelvekben. Skalár típusok A számtípusok lehetnek egészek, lebegőpontos, tört, és komplex számok. A bignum tetszőleges nagyságú vagy pontosságú számot tárolhatnak. A törtek számlálóval és nevezővel vannak reprezentálva, ami sok más nyelvben nem létezik. A Common Lisp ezeket a számtípusokat automatikusan konvertálja.
A character nem korlátozódik az ASCII-re. A legtöbb implementáció Unicode-ot használ.
A Lisp nyelvjárások ismerik a szimbólum típust, de más nyelvek alig. A szimbólum egy egyedi, elnevezett adatobjektum több résszel: tartalmaz nevet, értéket, függvényt, tulajdonságlistát és csomagot. Ezek közül az érték- és a függvénycellák a legfontosabbak. A Lispben a szimbólumokat általában úgy használják, mint a többi nyelvben az azonosítókat, de vannak más felhasználási módok is. A szimbólum kiértékelésekor a benne foglalt adatot kapjuk vissza. Egyes szimbólumok önmagukat értékelik ki, például a keywords csomag tagjai. A logikai értékeket is önkiértékelő szimbólumok reprezentálják, a t és a nil. A Common Lispben a szimbólumok névterekhez, csomagokhoz tartoznak.
A számértékek kerekítésére számos függvény áll rendelkezésre. A round a legközelebbi egészre kerekít. A szokásos kerekítéstől eltérően azonban a feles értékek helyett a két lehetőség közül a páros egészet veszi. A floor az alsó, a ceiling a felső egészrészt jelenti; a truncate csonkol. A törtrész a második visszatérési érték. Például (floor -2.5) értéke -3, 0.5; (ceiling -2.5) értéke -2, -0.5; (round 2.5) értéke 2, 0.5; és (round 3.5) értéke 4, -0.5.
Adatszerkezetek A listaszerű adatszerkezetek közé tartoznak a listák, a vektorok, a bitvektorok és a stringek. Mindegyikhez sok művelet tartozik.
Akárcsak a legtöbb Lisp nyelvjárásban, a listák Common Lispben is cons cellákból épülnek fel. A cons egy két slotú adatszerkezet, a lista fejét reprezentáló car, és a lista farkának megfelelő cdr. A listák cons cellák láncolatai. A car a lista egy elemére mutat, a cdr egy másik cons cellára hivatkozik, kivéve az utolsót, aminek értéke nil. A cons cellákból más adatszerkezetek, fák és körkörös hivatkozásokat tartalmazó szerkezetek építhetők. Ehelyett azonban ajánlott osztályokat és struktúrákat használni.
A Common Lisp támogatja a többdimenziós tömböket, amelyek dinamikusan átméretezhetők, és amelyekkel mátrixszámítások is végezhetők. Az egydimenziós tömbök vektorok. Egy tömb tartalmazhat különböző típusú elemeket, de specializálhatók egy típus tárolására, például egészek vektora. Egyes implementációk ennek ismeretében optimalizálják a feldolgozó algoritmusaikat. A szabvány tartalmaz két típusspecializált vektort: a stringet és a bitvektort.
A hash táblák kulcs-érték párokat tartalmaznak, amelyek bármilyen típusúak lehetnek.
A csomagok szimbólumokat tartalmaznak, és főként névterek kialakítására szolgálnak. Az export interfész elemeiként feltünteti a kívülről is látható szimbólumokat. A Struktúrának a nyelv rekord típusait nevezik. A C structjaira és a Pascal recordjaira hasonlítanak. Összetett adattípusok, amelyek akárhány mezőt tartalmazhatnak, ahol az érték típusa az összes típus közül választható. A mezőket slotoknak nevezik. Egyszeres öröklődést tesznek lehetővé.
Az osztályok a struktúrákra hasonlítanak, de több dinamikus lehetőséget és többszörös öröklődést biztosítanak. Az osztály objektumai példányok. A generikus függvények speciális esetek: egyszerre függvények és példányok. csomagok más csomagokat is tartalmazhatnak.
Függvények A Common Lisp támogatja a funkcionális paradigmát, azaz a függvények más objektumokhoz hasonlóan kezelhetők. Léteznek magasabb rendű függvények, amelyeknek argumentumai vagy visszatérési értékei függvények. Lehet névtelen és beágyazott függvényeket definiálni, amelyek külső változókhoz is hozzáférnek; lezártakat átadni, sőt, változóba függvényt helyettesíteni, és függvények egyenlőségét vizsgálni.
A magasabb rendű függvények a nyelv könyvtáraiban is fontosak, például a sort argumentuma egy összeghasonlító operátor és egy kulcsfüggvény, mint opcionális kulcsszó argumentum. Nemcsak skalár adatok rendezhetők, hanem összetett adatstruktúrák is egy adott kulcs szerint:
;; Listák rendezése a > és a < függvényekkel, mint összehasonlító operátorokkal: (sort (list 5 2 6 3 1 4) #'>) ; Returns (6 5 4 3 2 1) (sort (list 5 2 6 3 1 4) #'<) ; Returns (1 2 3 4 5 6) ;; Lista rendezése az allisták első eleme szerint : (sort (list '(9 A) '(3 B) '(4 C)) #'< :key #'first) ; Returns ((3 B) (4 C) (9 A))
A függvények kiértékelésének modellje egyszerű. Ha a kiértékelő lát egy (F A1 A2...)sorozatot, akkor feltételezi, hogy F a következők egyike: Speciális operátor (rögzített lista) Makró (előzőleg definiált) Függvénynév, ami lehet szimbólum, vagy lehet lambda.
Hogyha F függvénynév, akkor előbb az A1, A2, ..., An argumentumok értékelődnek ki balról jobbra, majd az F függvény meghívódik ezekkel a paraméterekkel. Funkcionális szempontból tekintve a nyelv mohó. Függvények definiálása Függvények a defun makróval definiálhatók. A definíció megadja a függvény és paraméterei nevét, meg a függvénytörzset:
(defun square (x) (* x x))
A definíciók tartalmazhatnak deklarációkat is, amelyek informálják a fordítót az optimalizációról és tartalmazzák a paraméterek típusát. Az itt megadott dokumentáció interaktívan előhívható:
(defun square (x) "Kiszámítja a single-float x négyzetét." (declare (single-float x) (optimize (speed 3) (debug 0) (safety 1))) (the single-float (* x x)))
Névtelen függvények lambda-kifejezésekkel adhatók meg, például (lambda (x) (* x x)). A Lisp programozási stílusára jellemző magasabb rendű függvényeknek sokszor érdemes névtelen függvényeket paraméterként átadni.
Lokális függvények definiálhatók a flet és a labels szavakkal:
(flet ((square (x) (* x x))) (square 3))
A függvények kezelését számos más operátor segíti, például a compile operátor, aminek hatására a függvény újrafordul.
Generikus függvények és metódusok A defgeneric generikus függvényeket, a defmethod metódusokat definiál. A generikus függvények metódusok gyűjteményei. A metódusok osztályokra vagy objektumokra specializálhatók. A generikus függvény hívásakor választódik ki a típusnak megfelelő függvény.
(defgeneric add (a b))
(defmethod add ((a number) (b number)) (+ a b))
(defmethod add ((a vector) (b number)) (map 'vector (lambda (n) (+ n b)) a))
(defmethod add ((a vector) (b vector)) (map 'vector #'+ a b))
(add 2 3) ; 5 (add #(1 2 3 4) 7) ; #(8 9 10 11) (add #(1 2 3 4) #(4 3 2 1)) ; #(5 5 5 5)
A generikus függvények is elsőfajú adattípusok. Még sok eszköz létezik a generikus függvények kezelésére. A függvények névtere A függvények névtere különbözik a többi adatétól; ez kulcsfontosságú különbség a Common Lisp és a Scheme között. A Common Lispben a defun, flet, labels, defmethod és a defgeneric operátorok hoznak létre függvény névtérbeli adatokat.
A függvények név szerinti paraméterátadásakor a function speciális operátort kell használni, ami rövidíthető a #' jellel. Erre példa a fent már szerepelt függvényátadás a sort operátornak. Az így átadott függvény a funcall operátorral hívható.
A Scheme kiértékelési módszere egyszerűbb, mivel csak egy névtér van, és minden kiértékelődik, nemcsak az argumentumok. Így az egyik nyelvjárásban írt kód nehezen értelmezhető a másik nyelvjárásban gyakorlott programozók számára. Például a Common Lispben szokás leíró neveket adni a változóknak, mint list vagy string. Ez a gyakorlat a Scheme-ben fontos függvényneveket takarhat el.
A Lisp programozók nem értenek egyet abban, hogy jó ötlet-e a két névtér. Erre Lisp-1 vs. Lisp-2 vitaként utalnak, ahol a számok a névterek számát jelölik. Ezek a nevek Richard P. Gabriel és Kent Pitman egy 1988-as cikkéből származnak, ahol alaposan kifejtik a témát.
Más adattípusok A fontosabb többi adattípus: A fájlokat és könyvtárakat reprezentáló nevek. A legtöbb operációs rendszernél általánosabb, ami támogatja hordozható Lisp programok írását. Az input és az output streamek szöveges vagy bináris adatok forrásait vagy céljait reprezentálják, mint a terminálok és a megnyitott fájlok. A Common Lisp rendelkezésre bocsát egy beépített álvéletlen számgenerátort. A véletlen állapotobjektumok az álvéletlen számok újrahasznosítható forrásai, ami lehetővé teszi magok megadását, vagy adott álvéletlen számsorozatok visszajátszását. Az állapotok hibákat, kivételeket és más fontos, reakcióra váró eseményeket reprezentálnak. Az osztályok első osztályú objektumok, és a metaobjektum osztályok (röviden metaosztályok) példányai. Az olvasótáblák ellenőrzik a Common Lisp fordítását. A nyelv szintaxisa megváltoztatható vagy kiterjeszthető azzal, hogy a programozó olvasótáblát változtat.
Hatókör Ahogy más nyelvek, a Common Lisp is névvel hivatkozik a változókra, a függvényekre és más objektumokra. A nevesített referenciáknak hatókörük van.
A név és az általa megnevezett objektum közötti kapcsolat a kötés. A hatókör azokat a körülményeket jelenti, ahol ez a kötés fennáll.
A hatókör meghatározói