A Clojure programozási nyelv

Szintaxis

A reader

A Clojure programok mint minden más programozási nyelvben, életútjukat szöveges formában (akár fájlokban, akár egy REPL felületen direkt inputként) kezdik. Más programozási nyelvekkel ellentétben, a szöveges reprezentációt először nem a fordító kezdi el beolvasni, hanem egy beolvasó modul, amit reader-nek hívunk. A reader a programszövegből egy adatszerkezetet állít elő, amit átad a fordítónak. Ez tehát azt jelenti, hogy minden Clojure program valójában egy adatszerkezet. A Clojure nyelv szintaxisát tehát maga a reader implementációja határozza meg, hiszen ez alakítja át a szöveget a megfelelő adatszerkezetre. Írható lenne olyan reader is, ami XML dokumentumokból, JSON-ból, stb. olvassa fel a programkódot, és ezt alakítaná a fordító számára is érthető adatszerkezetté. De a Clojure beépített reader-e (read függvény) nem csinál ilyesmit, így a nyelv szintaxisának leírásakor tehát erre hagyatkozunk. A reader-re tehát tekintsünk úgy, mint egy egyszerű parser-re, ami a programszöveget felolvasva különböző műveleteket végez, kimenete pedig a kódnak megfelelő adatszerkezet.

Makró karakterek

Makró karaktereknek hívjuk azokat a karaktereket, amik befolyásolják a reader működését: beolvasásukkor a beolvasott karakternek megfelelő, ún. reader makrók hajtódnak végre.

Makró karakterek:
Idézőjelezés (Quote):'form
Karakterek:\a \b \c
Kommentek:; komment
Metaadatok:^metaadat vagy ^{kulcs ertek}
Dereferencia:@form
Syntax-quote:` ("backtick" karakter)
Unquote:~
Unquote-splicing:~@
A #-hez tartozó makró karakterek:
Halmazok:#{:a :b :c}
Regexpek:#"pattern"
Var-quote:#'x
Anonymous függvény:#(...)
Következő reader form teljesen figyelmen kívül hagyása:#_

Reader form-ok

Form-nak (vagy magyarítva formának) hívhatjuk a reader által beolvasott szintaktikus egységeket. A következő táblázatban példákkal illusztráljuk a különböző reader form-okat:
Reader form-ok
Szimbólumok:Pl.: abcd, *abcd*, +*!?, stb.Nem-numerikus karakterrel kezdődnek, és alfanumerikus vagy *, +, !, -, _, ? karaktereket tartalmazhatnak.
Literálok: Pl.: 42, "abcd", nil, true, false, \c, :foo A példákban rendre: szám-, szöveg-literálok, nil érték, logikai értékek, a "c" karakter, és egy kulcsszó (kulcsszavak szintaxisa megegyezik a szimbólumokéval, a kettőspontot leszámítva)
Listák: Pl.: (a b c), (42 "b" nil), (\c :alma nil), stb. Heterogén típusú listák. Szintaxis: az elemek zárójelek között.
Vektorok: Pl.: [a b c], [42 "b" nil], [\c :alma nil], stb. Heterogén típusú vektorok. Szintaxis: az elemek szögletes zárójelek között.
Hash map-ek: Pl.: {:key1 "value1" :key2 "value2"}, {1 :value1 "key2" "value2"}, stb. Kulcs-érték párok, kapcsoszárójelek között felsorolva. Heterogén: tetszőleges kulcsok, tetszőleges értékek.
Halmazok: Pl.: #{:a :b :c}, #{:a 23 [2 3 4 5]} stb. Heterogén típusú halmazok. A #{...} szintaxist feltüntettük a reader makróknál is.

Megjegyzések

Az első bekezdésben volt róla szó, hogy minden Clojure program valójában egy olyan adatszerkezet, ami a nyelvvel közvetlenül leírható. Azokat a nyelveket, amikben a programkód és az adat nem különül el egymástól, homoikonikus nyelveknek nevezzük. Az összes Lisp nyelv ilyen. Az ilyen nyelvekben nem léteznek tehát lefoglalt szavak, operátorok, és hasonlók. Ez a nyelv szintaxisleírását leegyszerűsíti. Az infix jelölés miatt az operátorok precedenciája sem jelent gondot:
	user=> (* (+ 4 5) (/ 7 5))   ; operátor-precedenciával sem kell foglalkozni
	63/5

A reader továbbá sokszor úgynevezett meta-információval lát el bizonyos kódrészleteket. Például a meta-információ tartalmazhatja, hogy az adott var melyik fájlban és melyik sorban került definiálásra. Sokszor a metainformációba kerül a függvények docstring-je, azaz a dokumentációt tartalmazó string, ami ilyen módon szintén része lesz a kódot tartalmazó adatszerkezetnek. A függvények elő- és utófeltétele, és a tesztesetei is ide kerülnek. Egy objektum meta-információját tartalmazó hash-map lekérdezhető a meta függvénnyel, ami, ha nincs ilyen információ, akkor nil-t ad vissza. A metainformáció módosítása úgy történik, hogy a with-meta függvény egy olyan objektumot ad vissza, ami már az új meta-információval rendelkezik. Az immutabilitás miatt azonban a régi objektum továbbra is a régi metainformációt tartalmazza.