A Concurrent Clean a funkcionális nyelvek családjába tartozik. Hollandiában, a Nijmegeni Egyetemen fejlesztették ki 1987 környékén, a Lean gráfátíró kísérleti nyelvből fejlődött ki. A Concurrent jelzőt fejlődésének csak egy viszonylag késői fázisában kapta, amikor párhuzamossági funkciókkal bővítették, de ez ma még eléggé gyerekcipőben jár. Funkcionális nyelvi képességei viszont teljesek, ha nem is a legteljesebbek a hasonló nyelvekhez viszonyítva. Közel áll a Haskell-hez, de több olyan nyelvi elemet tartalamaz amit a Haskell '98 nem. Sok társával szemben viszont ezen a nyelven a való világgal kommunikáló, interaktív programokat is meg lehet fogalmazni (ami funkcionális nyelvek esetén nem is olyan triviális).
Valamennyi támogatott platformra (Windows, Linux, Mac) natív kódot készít a fordító.
Első példaként nézzük meg, hogyan néz ki Cleanben a világ legnépszerűbb programja:
melyet a következő parancsokkal fordíthatunk és futtathatunk le:
Elsőként pár szót ejtenénk a funkcionális nyelvek sajátosságairól, hiszen a későbbieket ennek fényében kell értelmezni, ugyanakkor ez a gondolkodásmód különbözik a hagyományos imperatív, illetve objektumorientált nyelvekétől, és nem biztos, hogy minden olvasó ismeri.
A Clean precízebben megfogalmazva a modern funcionális nyelvek közé tartozik, mivel az összes ezekre a nyelvekre jellemző sajátosságokat megvalósítja (zárójelben a fejezet címe ahol részletesebben van tárgyalva a fogalom):
A funkcionális nyelvekben az adatok, konstansok, kifejezések alapvetően (az elemi értékek kivételével) gráfokként vannak reprezentálva. A gráf minden egyes pontjában egy függvény — például egy operátor — vagy egy adatkonstruktor szimbóluma van, a pontból kivezető irányított élek pedig — ha vannak — az alkalmazott objektumokra mutatnak. Pl. a 3 * 5 kifejezés (ami prefix formában (*) 3 5 alakú) gráfjában három pont található rendre a (*), 3, 5 címkékkel, a (*) pontból irányított él vezet a 3 és 5 pontokba. Az Add (Succ Zero) Zero kifejezés (amely a szokásosan Add (Succ (Zero), Zero) alakban írt kifejezés Cleanbeli formája) gráfjában is három pont van, az Add kettes aritású függvény címkéjétől a Succ-hoz és a Zero-hoz vezet egy-egy él, míg a Succ-tól (melynek aritása egy) a Zero-hoz.
Mit lehet kezdeni ezekkel a gráfokkal? Függvényeket definiálhatunk, melyek tulajdonképpen gráfújraírási szabályok. Az Add függvényt például a következőképpen írhatjuk le:
A kifejezések kiértékelése azt jelenti, hogy a rendelkezésre álló gráf-újraírási szabályok bal oldalán szereplő mintákat megpróbáljuk illeszteni a gráfjainkra, majd helyettesíteni azt a jobb oldallal.
Rövidebben fogalmazva tehát nem más mint átírási lépések sorozata, valamint az ezek során lehetséges redukciók elvégzése. Az átírási lépés során a föggvényt helyettesítjük a függvény törzsével, mindaddig amíg
el nem érjük a normálformát. A kiértékelési sorrend/stratégia, azaz a redex-ek (reducible expressions) kiválasztási sorrendje Clean esetén lusta kiértékelésű
(lsd. Adattípusok, változók, kifejezések fejezeten belül Kiértékelési sorrend). A lusta kiértékelés mindig megtalálja a normálformát, ha létezik konfluens átíró rendszerekben. Ezt nevezzük egyértelmű normálformának.
A konfluens átíró rendszer pedig egy olyan rendszer, amelyben az átírási sorrend nincs hatással a végeredményre, csak arra, hogy normálformára jutunk-e. Ilyen például a lambda-kalkulus.
A fenti példában az Add (Succ a) z minta illeszkedik, az előírt helyettesítés után a Succ (Add Zero Zero) kifejezést kapjuk, melynek gráfja a következőképpen fog kinézni: a Succ címkétől él mutat az Add-hoz,
amiből két párhuzamos él vezet ugyanahhoz a Zero ponthoz (az Add mindkét paramétere ugyanaz). Ezt a gráfot tovább lehet alakítani az Add függvény másik mintája alapján, ennek eredményeképpen a Succ Zero kifejezést
kapjuk eredményül.
Már ebben a kis példában is láthattuk, hogy miért jó a gráfreprezentáció: ugyanarra a konstrukcióra több él is mutathat, így a kifejezés leírásánál helyet takaríthatunk meg. Ezen kívül ciklikus struktúrák is létrehozhatók, amelyek a gráfújraírási szabályok segítségével a fent látotthoz hasonló módon alakíthatóak tovább.
Egy Clean program végrehajtása nem más, mint a kezdeti (ún. start-) kifejezésből kiindulva addig végezni a kiértékelési stratégia által diktált sorrendben az átalakításokat, amíg lehetséges. Mindeközben szemétgyűjtés gondoskodik azoknak a gráfdaraboknak a törléséről, amelyekre már nem hivatkozik senki. Az ezután megmaradó gráf a program eredménye.
A graph program futásának eredménye:
A -nt kapcsoló eltünteti a végrehajtási idők kijelzését:
A cyclic program futtatásával a kettőhatványok végtelen listájának kiíratására utasítjuk a gépet:
Csak akkor fogjuk a fenti eredményt látni, ha a program elindítása után azt gyorsan félbeszakítjuk, különben addig fognak a számok szaladni a képernyőnkön, míg le nem állítjuk. A negatív szám és utána a nullák a túlcsordulás miatt kerültek a lista végére.