Common Lisp

Common Lisp on Lisp-ohjelmointikieli, jolle on ANSI-standardi X3.226-1994. Koska Common Lisp kehitettiin standardisoimaan sitä edeltävien Lisp-murteiden ominaisuudet, se on ennemminkin kielen määritelmä kuin toteutus. Standardinmukaisia Common Lisp -toteutuksia (kääntäjiä ja tulkkeja) on monia, niin yksityisiä kuin avoimen lähdekoodin toteutuksia.
Common Lisp on yleiskäyttöinen ohjelmointikieli, toisin kuin jotkin Lisp-murteet, kuten Emacs Lisp ja AutoLISP, jotka ovat vain tietylle ohjelmalle kehitettyjä laajennoskieliä. Toisin kuin monet aikaisemmat Lisp-murteet, Common Lisp (kuten myös Scheme) käyttää muuttujien staattista näkyvyyttä.
Common Lisp on monta ohjelmointiparadigmaa tukeva kieli, joka:
Syntaksi.
Common Lisp on Lispin murre, joten Lispin tapaan se käyttää S-lausekkeita sekä koodin että datan esittämiseen. Funktioiden ja makrojen kutsut kirjoitetaan listoina siten, että funktion nimi on listan ensimmäinen alkio. Esimerkkejä:
 (+ 2 2) ; laskee yhteen luvut 2 ja 2, tuloksena 4.
 (setf pii 3.1415) ; asettaa muuttujan "pii" arvoksi 3.1415
 ; Funktio, joka laskee luvun neliön:
 (defun nelio (x) 
 (* x x))
 ; Suoritetaan funktio:
 (nelio 3) ; Palauttaa luvun 9
 ; let on Common Lispin operaattori, joka sitoo muuttujia oman runkonsa suorituksen ajaksi.
 ; Jos a ja b oli jo määritelty ennen tätä lauseketta, vanhat arvot palautuvat, kun
 ; let-lauseke on suoritettu.
 (let ((a 6) (b 4)) 
 (+ a b)) ; Palauttaa luvun 10
Datatyypit.
Common Lispissä on runsaasti datatyyppejä, enemmän kuin monissa muissa ohjelmointikielissä.
Skalaarityypit.
"Numeeriset" tyypit sisältävät kokonaisluvut, rationaaliluvut, liukuluvut ja kompleksiluvut. Common Lisp sisältää myös bignum-tyypin esittämään mielivaltaisen suuria ja tarkkoja lukuja. ratio-tyyppi esittää rationaaliluvut tarkkoina arvoina, mikä on mahdotonta suuressa osassa kieliä. Tarvittaessa Common Lisp suorittaa automaattisen tyyppimuunnoksen numeeristen tyyppien välillä.
Common Lispin "merkki" (character-tyyppi) ei ole rajoittunut vain ASCII-merkkeihin – onhan Lisp on kehitetty ennen ASCII:ta. Jotkut modernit toteutukset tuntevat Unicode-merkistön.
"Symboli" (symbol-tyyppi) on yleinen Lisp-murteissa, mutta suurelta osin tuntematon muissa kielissä. Symboli on uniikki, nimetty data-arvo. Symbolit Lispissä vastaavat muiden kielten nimiä, kuten funktioiden ja muuttujien nimiä. Lispissä ne ovat kuitenkin yleiskäyttöisempiä ja niitä voi käyttää myös sellaisenaan. Normaalisti, kun symboli evaluoidaan, sitä vastaavan muuttujan arvo palautetaan. Avainsanasymbolit, kuten :foo kuitenkin evaluoituvat takaisin itsekseen, ja totuusarvot esitetään Common Lispissä niille varatuilla symboleilla t ja nil.
Tietorakenteet.
Common Lispin "sekvenssi"-tyyppeihin kuuluvat listat, vektorit, bittivektorit ja merkkijonot. Common Lispissä on monia funktioita, jotka toimivat mille tahansa sekvenssille.
Kuten muissakin Lisp-murteissa, Common Lispissä "listat" rakentuvat pareista (cons). Pari on tietorakenne, jossa on kaksi alkiota, ensimmäinen on "car" ja toinen on "cdr". Lista on linkitetty ketju pareja siten, että jokaisen parin car osoittaa listan alkioon ja cdr osoittaa seuraavaan pariin – paitsi listan viimeisellä parilla, jonka cdr-alkio on nil-arvo. Pareja voi helposti käyttää myös esittämään esimerkiksi puita ja muita muita monimutkaisia tietorakenteita.
Common Lisp tukee moniulotteisia "taulukoita", joiden kokoa voi tarvittaessa muuttaa dynaamisesti. Moniulotteisia taulukoita voi käyttää esimerkiksi matriisilaskennassa. "Vektori" on yksiulotteinen taulukko. Taulukot voivat sisältää minkä tahansa tyyppistä dataa (myös siten että taulukon eri alkiot ovat erityyppisiä), tai ne voi erikoistaa sisältämään vain yhden tyyppisiä alkioita. Monet Common Lisp -toteutukset pystyvät optimoimaan taulukko-operaatioita, kun taulukko on erikoistettu yhdelle tyypille. Kahdelle tietylle tyypille erikoistetulle taulukolle on oma nimi: "Merkkijono" on vektori, joka sisältää merkkejä, ja "bittivektori" on vektori joka sisältää bittejä.
"Hajautustauluihin" talletetaan data-arvojen välisiä assosiaatioita. Mitä tahansa objektia voi käyttää avaimena tai arvona. Hajautustaulujen koko muuttuu automaattisesti tarvittaessa.
"Paketit" ovat symbolikokoelmia. Niitä käytetään pääasiassa erottamaan ohjelman eri osat nimiavaruuksiksi. Paketti voi "julkistaa" (export) symboleita merkiten ne osaksi paketin julkista rajapintaa.
"Tietueet" esittävät mielivaltaisen monimutkaisia tietorakenteita, joissa on alkioita. Ne vastaavat C:n structeja tai Pascalin recordeja.
Luokkien "instanssit" ovat samanlaisia kuin tietueet, mutta liittyvät Common Lispin oliolaajennukseen, CLOS:iin.
Funktiot.
Common Lispissä "funktio" on datatyyppi. On esimerkiksi mahdollista kirjoittaa funktioita, jotka ottavat parametreikseen toisia funktiota tai palauttavat funktioita. Tämä mahdollistaa erittäin yleiskäyttöisten operaatioiden toteuttamisen.
Common Lispin kirjastofunktiot tukeutuvat tällaisiin korkeamman asteen funktioihin. Esimerkiksi sekvenssin järjestävälle codice_1-funktiolle annetaan parametrina vertailufunktio. Tämä mahdollistaa minkä tahansa tyyppisen datan järjestämisen.
 (sort (list 5 2 6 3 1 4) #'&gt;)
 ; Järjestää listan käyttämällä &gt; -funktiota.
 ; Palauttaa (6 5 4 3 2 1).
 (sort (list '(9 a) '(3 b) '(4 c))
 #'(lambda (x y) (&lt; (car x) (car y))))
 ; Järjestää listan jokaisen sisäkkäisen listan ensimmäisen elementin (car) perusteella.
 ; Palauttaa ((3 b) (4 c) (9 a)).
Funktioiden evaluointimalli on hyvin yksinkertainen. Kun kohdataan kaava codice_2, oletetaan että F on jokin seuraavista:
Jos F on funktion nimi, argumentit A1, A2, ..., An evaluoidaan vasemmalta oikealle, ja funktio suoritetaan näillä argumenteilla.
Funktioiden määrittely.
Makrolla codice_4 määritellään funktioita.
 (defun nelio (x)
 (* x x))
Funktion määrittely voi sisältää "julistuksia" (declaration), jotka antavat kääntäjälle vihjeitä optimointiasetuksista tai argumenttien tyypeistä. Ne voivat myös sisältää "dokumentaatiomerkkijonoja" (docstring), joita voidaan käyttää interaktiiviseen dokumentaatioon.
 (defun nelio (x)
 (declare (number x) (optimize (speed 3) (debug 0) (safety 1)))
 "Laskee luvun x neliön."
 (* x x))
Nimettömiä funktioita voi määritellä käyttämällä operaattoria codice_3. Lisp-ohjelmointityyli käyttää usein korkeamman asteen funktioita, joille on hyödyllistä antaa nimettömiä funktioita argumentteina.
Funktioiden määrittelyyn ja käsittelyyn on myös muita operaattoreita. Funktion voi esimerkiksi kääntää (tai uudelleenkääntää) käyttäen operaattoria codice_6. (Jotkin Lisp-toteutukset ajavat funktioita oletuksena tulkissa ja kääntävät vasta kehotuksesta; toiset kääntävät kaikki funktiot lennossa.)
Funktioiden nimiavaruus.
Funktioiden nimiavaruus on erillinen muuttujien nimiavaruudesta. Tämä on suurin ero Common Lispin ja Schemen välillä. Joitain operaattoreita, jotka määrittelevät nimiä funktioiden nimiavaruuteen, ovat codice_4, codice_8, ja codice_9.
Jotta funktiolle voisi antaa argumentiksi toisen funktion nimen perusteella, täytyy käyttää erityisoperaattoria codice_10, jonka voi lyhentää codice_11. Ensimmäinen codice_1-esimerkki viittaa funktion, jonka nimi on codice_13 funktioiden nimiavaruudessa, lausekkeella codice_14.
Schemen evaluointimalli on yksinkertaisempi: On vain yksi nimiavaruus, ja kaikki listalausekkeen alkiot evaluoidaan – ei ainoastaan argumentteja. Siksi toisella murteella kirjoitettu koodi voi olla harhaanjohtavaa toista murretta osaavalle: Esimerkiksi moni Common Lisp -ohjelmoija käyttää mielellään kuvaavia muuttujien nimiä kuten "list" tai "string", mikä aiheuttaisi ongelmia Schemessä, koska muuttujat peittäisivät paikallisesti samannimiset funktiot.
Muut tyypit.
Common Lispissä on muitakin datatyyppejä, kuten:
Common Lispissä on myös työkalut olio-ohjelmointiin, Common Lisp Object System eli CLOS, joka on yksi kaikkein voimakkaimmista oliomalleista.
Makrot.
Lispin "makrot" muistuttavat ulkoisesti funktioita. Kuitenkin siinä missä funktio esittää evaluoitavaa lauseketta, makro esittää ohjelman lähdekoodin muuntamista muodosta toiseen.
Makrot mahdollistavat uusien syntaktisten muotojen luomisen kieleen. Esimerkiksi seuraava makro tarjoaa codice_15-silmukan, joka voi olla tuttu muista kielistä, kuten Perlistä:
 (defmacro until (test &amp;body body)
 `(do ()
 (,test)
 ,@body))
 ; esimerkki
 (until (= (random 10) 0)
 (write-line "Hello"))
Kaikki makrot "avataan" ennen kuin niitä sisältävä koodi suoritetaan tai käännetään. Makroja voi ajatella funktioina, jotka ottavat parametreina ja palauttavat jäsennyspuita (Lispin S-lausekkeita). Nämä funktiot suoritetaan ennen koodin suorittamista tai kääntämistä, ja ne tuottavat varsinaisen lähdekoodin. Makrot kirjoitetaan tavallisella Common Lispillä, ja ne voivat käyttää mitä tahansa tarjolla olevaa funktiota. `-merkintä (lainausmerkki "väärin päin") on Common Lispin erityisesti makroja varten tarkoitettu merkintä, joka yksinkertaistaa tavallista tapausta, jossa makro korvataan tietyn malliseksi koodiksi.
Toteutukset.
Common Lisp on määritelty paperilla (kuten Ada tai C) eikä yhdessä toteutuksessa (kuten Perl tai Python). Common Lispille on monia toteutuksia, ja standardi ilmaisee alueet, joissa ne voivat oikeaoppisesti erota toisistaan. Kaupallisia toteutuksia ovat Allegro Common Lisp ja LispWorks. Vapaista toteutuksista lienee suosituin olevan Steel Bank Common Lisp (SBCL). Usein ohjelmoitaessa käytetään GNU Emacs-tekstimuokkainta ja Common Lispille suunnattua SLIME-kehitysympäristöä. Kuitenkin muitakin vaihtoehtoja on tarjolla.
Lisäksi toteutusten mukana on tapana tulla myös funktiokirjastoja, jotka tarjoavat toiminnallisuuksia, joita ei ole kuvattu standardissa. Avoimen lähdekoodin kirjastoja on luotu tukemaan näitä ominaisuuksia siirrettävällä tavalla, mm. Common-Lisp.net .
Suurin osa Common Lisp -toteutuksista kääntää funktiot natiiviksi konekieleksi. Toiset kääntävät tavukoodiksi, mikä vähentää nopeutta mutta parantaa binäärikoodin siirrettävyyttä. Se harhaluulo, että Lisp on puhtaasti tulkattu kieli, johtuu luultavasti siitä, että Common Lisp -ympäristö tarjoaa interaktiivisen kehotteen (REPL), johon voi kirjoittaa koodia, ja siitä, että funktiot käännetään yksi kerrallaan.