Clojure-syntaks 101
I dag skal jeg vise deg all syntaksen i Clojure. I motsetning til hva du tror så er det en ganske interessant øvelse. Det er nemlig mer til dette språket enn mange parenteser.
I Clojure kan vi opprette alle de vanligst brukte datatypene med dedikert syntaks, med såkalte dataliteraler. Du kjenner nok igjen en del av dem.
Strenger
"Hei på deg!"
Tall
3.14
42
Booleans
true
false
Symboler og nøkkelord
Clojure har også to datatyper som oftest brukes til å referere til ting.
Symboler ser ut som det mange andre språk kaller “identifiers”:
name
lower-case
parenteser.page/render-page
Nøkkelord (keywords) brukes til navngivning og som nøkler i maps, enum-verdier osv:
:name
:page/kind
:page.kind/frontpage
Både symboler og nøkkelord kan ha navnerom, som står foran skråstreken i eksemplene over. Jeg har tidligere skrevet litt om bruk av nøkler.
Jeg kom til Clojure fra Ruby. Ruby kaller artig nok :name
for et symbol 😅
Clojure og Ruby bruker forskjellige navn om denne datatypen, men bruker den på
samme måte.
Collections
Clojure har dataliteraler for collections også.
Vektorer
Vektorer ligner mye på arrays i andre språk, og har effektiv indeksoppslag og appends. Du kan bruke komma til å separere elementene, men du må ikke. Clojure behandler komma som whitespace.
["Magnar" "Christian" "Ole-Marius"]
Lister
(1 2 3)
Sett
Sett er en samling av unike elementer.
#{1 2 3 4}
Maps
Maps er den datastrukturen vi bruker aller mest til å modellere data i Clojure. Den kan ha vilkårlige typer som både nøkler og verdier, men veldig ofte er det keywords som brukes som nøkler.
{:name "Christian"
:employed? true
:children 2}
Datastrukturer? Hvor er syntaksen?
Greit, Clojure har noen dataliteraler. Men hva med syntaksen? Du kan faktisk allerede hente diplomet ditt, for du kjenner nå 99% av syntaksen til Clojure. Hva? Jo, nå skal du høre: Clojure-kode uttrykkes med Clojure sine datastrukturer.
Her er bittelitt mer syntaks: ;
starter en kommentar. Konvensjonen tilsier at
vi bruker ;;
.
La oss se på en funksjon:
(defn greet [name]
(str "Hello, " name))
Hva ser vi her? Jo en liste med blandet innhold:
( ;; Liste
defn ;; Symbol
greet ;; Symbol
[name] ;; Vektor med et symbol
( ;; Ny liste
str ;; Symbol
"Hello, " ;; Streng
name ;; Symbol
)
)
Da blir det forhåpentligvis litt tydeligere hvorfor parentesene hele tiden står på “feil” side: funksjonskall, funksjonsdefinsjoner og alt annet som er omringet av parenteser er lister.
Kode er data. Sagt på en annen måte: I Clojure skriver du i praksis AST-en direkte. Hva gir det oss? MASSE!
Når kode er data så kan vi redigere koden med strukturelle operasjoner. Dette er både mer presist og mer kraftfult enn å manuelt redigere syntaks. Se bare hva Magnar får til når han er gira.
Når kode er data, kan vi skrive om koden vår med såkalt metaprogrammering med
makroer. Et utrolig skarpt verktøy som
vi ikke bruker så ofte. Men makroer har eksempelvis gitt oss Go sin
go
-konstrukt som et bibliotek. Dette
er en endring som i de aller fleste andre språk hadde krevd ny syntaks og støtte
i den offisielle kompilatoren. Med makroer kan miljøet rundt utvide språket med
biblioteker. Ganske kult!
Når kode er data, så kan vi lett bygge DSL-er som “ser ut som” kode, med ren data. Det betyr at eksempelvis konfigurasjon kan ligge tett opptil koden vår uten at den trenger å være Touring-komplett.
Når kode er data, kan vi bruke standardbiblioteket som vi bruker til dataprosessering til å manipulere koden vår.
Data er fete greier, og i Clojure er sørenmeg til og med koden data. Er det rart vi er glad i Clojure?