clojure
Samlingar och sekvenser
Sök…
Syntax
-
'()
→()
-
'(1 2 3 4 5)
→(1 2 3 4 5)
-
'(1 foo 2 bar 3)
→(1 'foo 2 'bar 3)
-
(
list
1 2 3 4 5)
→(1 2 3 4 5)
-
(
list*
[1 2 3 4 5])
→(1 2 3 4 5)
-
[]
→[]
-
[1 2 3 4 5]
→[1 2 3 4 5]
-
(
vector
1 2 3 4 5)
→[1 2 3 4 5]
-
(
vec
'(1 2 3 4 5))
→[1 2 3 4 5]
-
{}
=>{}
-
{:keyA 1 :keyB 2}
→{:keyA 1 :keyB 2}
-
{:keyA 1, :keyB 2}
→{:keyA 1 :keyB 2}
-
(
hash-map
:keyA 1 :keyB 2)
→{:keyA 1 :keyB 2}
-
(
sorted-map
5 "five" 1 "one")
→{1 "one" 5 "five"}
(poster sorteras efter tangent när de används som en sekvens) -
#{}
→#{}
-
#{1 2 3 4 5}
→#{4 3 2 5 1}
(oordnad) -
(
hash-set
1 2 3 4 5)
→#{2 5 4 1 3}
(oordnad) -
(
sorted-set
2 5 4 3 1)
→#{1 2 3 4 5}
samlingar
Alla inbyggda Clojure-samlingar är oföränderliga och heterogena, har bokstavlig syntax och stöder conj
, count
och seq
funktioner.
-
conj
returnerar en ny samling som motsvarar en befintlig samling med en artikel "tillagd", antingen i "konstant" eller logaritmisk tid. Vad exakt detta betyder beror på samlingen. -
count
ger antalet objekt i en samling i konstant tid. -
seq
returnerarnil
för en tom samling, eller en sekvens av objekt för en icke-tom samling, i konstant tid.
listor
En lista betecknas med parenteser:
()
;;=> ()
En Clojure-lista är en enskilt länkad lista . conj
"förenar" ett nytt element i samlingen på den mest effektiva platsen. För listor är detta i början:
(conj () :foo)
;;=> (:foo)
(conj (conj () :bar) :foo)
;;=> (:foo :bar)
Till skillnad från andra samlingar utvärderas icke-tomma listor som samtal till speciella formulär, makron eller funktioner när de utvärderas. Därför, medan (:foo)
är den bokstavliga representationen av listan som innehåller :foo
som dess enda objekt, kommer utvärdering (:foo)
i en REPL att leda till att en IllegalArgumentException
kastas eftersom ett sökord inte kan åberopas som en null funktion .
(:foo)
;; java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :foo
För att förhindra att Clojure utvärderar en icke-tom lista kan du quote
den:
'(:foo)
;;=> (:foo)
'(:foo :bar)
;;=> (:foo :bar)
Tyvärr gör detta att elementen inte utvärderas:
(+ 1 1)
;;=> 2
'(1 (+ 1 1) 3)
;;=> (1 (+ 1 1) 3)
Av detta skäl vill du vanligtvis använda list
, en variadisk funktion som utvärderar alla dess argument och använder dessa resultat för att konstruera en lista:
(list)
;;=> ()
(list :foo)
;;=> (:foo)
(list :foo :bar)
;;=> (:foo :bar)
(list 1 (+ 1 1) 3)
;;=> (1 2 3)
count
ger antalet objekt i konstant tid:
(count ())
;;=> 0
(count (conj () :foo))
;;=> 1
(count '(:foo :bar))
;;=> 2
Du kan testa om något är en lista med list?
predikat:
(list? ())
;;=> true
(list? '(:foo :bar))
;;=> true
(list? nil)
;;=> false
(list? 42)
;;=> false
(list? :foo)
;;=> false
Du kan få det första elementet i en lista med peek
:
(peek ())
;;=> nil
(peek '(:foo))
;;=> :foo
(peek '(:foo :bar))
;;=> :foo
Du kan få en ny lista utan det första elementet med pop
:
(pop '(:foo))
;;=> ()
(pop '(:foo :bar))
;;=> (:bar)
Observera att om du försöker pop
en tom lista får du en IllegalStateException
:
(pop ())
;; java.lang.IllegalStateException: Can't pop empty list
Slutligen är alla listor sekvenser, så du kan göra allt med en lista som du kan göra med någon annan sekvens. I själva verket, med undantag för den tomma listan, kalla seq
på en lista returnerar exakt samma objekt:
(seq ())
;;=> nil
(seq '(:foo))
;;=> (:foo)
(seq '(:foo :bar))
;;=> (:foo :bar)
(let [x '(:foo :bar)]
(identical? x (seq x)))
;;=> true
sekvenser
En sekvens är ungefär som en lista: det är ett oändligt objekt som kan ge dig sitt first
element eller rest
av dess element i konstant tid. Du kan också cons
truct en ny sekvens från en befintlig sekvens och ett objekt att hålla i början.
Du kan testa om något är en sekvens med sekvensen seq?
predikat:
(seq? nil)
;;=> false
(seq? 42)
;;=> false
(seq? :foo)
;;=> false
Som du redan vet är listor sekvenser:
(seq? ())
;;=> true
(seq? '(:foo :bar))
;;=> true
Allt du får genom att ringa seq
eller rseq
eller keys
eller vals
en icke-tom samling är också en sekvens:
(seq? (seq ()))
;;=> false
(seq? (seq '(:foo :bar)))
;;=> true
(seq? (seq []))
;;=> false
(seq? (seq [:foo :bar]))
;;=> true
(seq? (rseq []))
;;=> false
(seq? (rseq [:foo :bar]))
;;=> true
(seq? (seq {}))
;;=> false
(seq? (seq {:foo :bar :baz :qux}))
;;=> true
(seq? (keys {}))
;;=> false
(seq? (keys {:foo :bar :baz :qux}))
;;=> true
(seq? (vals {}))
;;=> false
(seq? (vals {:foo :bar :baz :qux}))
;;=> true
(seq? (seq #{}))
;;=> false
(seq? (seq #{:foo :bar}))
;;=> true
Kom ihåg att alla listor är sekvenser, men inte alla sekvenser är listor. Medan listor stöder peek
och pop
och count
i konstant tid behöver i allmänhet en sekvens inte stödja någon av dessa funktioner. Om du försöker ringa peek
eller pop
på en sekvens som inte också stöder ClassCastException
får du en ClassCastException
:
(peek (seq [:foo :bar]))
;; java.lang.ClassCastException: clojure.lang.PersistentVector$ChunkedSeq cannot be cast to clojure.lang.IPersistentStack
(pop (seq [:foo :bar]))
;; java.lang.ClassCastException: clojure.lang.PersistentVector$ChunkedSeq cannot be cast to clojure.lang.IPersistentStack
(peek (seq #{:foo :bar}))
;; java.lang.ClassCastException: clojure.lang.APersistentMap$KeySeq cannot be cast to clojure.lang.IPersistentStack
(pop (seq #{:foo :bar}))
;; java.lang.ClassCastException: clojure.lang.APersistentMap$KeySeq cannot be cast to clojure.lang.IPersistentStack
(peek (seq {:foo :bar :baz :qux}))
;; java.lang.ClassCastException: clojure.lang.PersistentArrayMap$Seq cannot be cast to clojure.lang.IPersistentStack
(pop (seq {:foo :bar :baz :qux}))
;; java.lang.ClassCastException: clojure.lang.PersistentArrayMap$Seq cannot be cast to clojure.lang.IPersistentStack
Om du count
på en sekvens som inte implementerar count
i konstant tid får du inte ett fel; istället kommer Clojure att korsa hela sekvensen tills den når slutet och sedan returnerar antalet element som den korsade. Detta innebär att count
för allmänna sekvenser är linjär, inte konstant, tid. Du kan testa om något stöder konstant count
med det counted?
predikat:
(counted? '(:foo :bar))
;;=> true
(counted? (seq '(:foo :bar)))
;;=> true
(counted? [:foo :bar])
;;=> true
(counted? (seq [:foo :bar]))
;;=> true
(counted? {:foo :bar :baz :qux})
;;=> true
(counted? (seq {:foo :bar :baz :qux}))
;;=> true
(counted? #{:foo :bar})
;;=> true
(counted? (seq #{:foo :bar}))
;;=> false
Som nämnts ovan kan du använda first
att få det första elementet i en sekvens. Observera att first
kommer att kalla seq
på deras argument, så det kan användas på allt "seqable", inte bara faktiska sekvenser:
(first nil)
;;=> nil
(first '(:foo))
;;=> :foo
(first '(:foo :bar))
;;=> :foo
(first [:foo])
;;=> :foo
(first [:foo :bar])
;;=> :foo
(first {:foo :bar})
;;=> [:foo :bar]
(first #{:foo})
;;=> :foo
Som nämnts ovan kan du använda rest
att få en sekvens som innehåller alla utom det första elementet i en befintlig sekvens. Liksom first
, kallar det seq
på sin argument. Men det kallar inte seq
om sitt resultat! Detta innebär att om du ringer rest
på en sekvens som innehåller färre än två objekt kommer du tillbaka ()
istället för nil
:
(rest nil)
;;=> ()
(rest '(:foo))
;;=> ()
(rest '(:foo :bar))
;;=> (:bar)
(rest [:foo])
;;=> ()
(rest [:foo :bar])
;;=> (:bar)
(rest {:foo :bar})
;;=> ()
(rest #{:foo})
;;=> ()
Om du vill komma tillbaka nil
när det inte finns fler element i en sekvens, kan du använda next
istället för rest
:
(next nil)
;;=> nil
(next '(:foo))
;;=> nil
(next [:foo])
;;=> nil
Du kan använda cons
funktionen för att skapa en ny sekvens som kommer att returnera det första argumentet för det first
och det andra argumentet för rest
:
(cons :foo nil)
;;=> (:foo)
(cons :foo (cons :bar nil))
;;=> (:foo :bar)
Clojure tillhandahåller ett stort sekvensbibliotek med många funktioner för att hantera sekvenser. Det viktiga med detta bibliotek är att det fungerar med allt "sökbart", inte bara listor. Det är därför begreppet en sekvens är så användbart; det betyder att en enda funktion, som reduce
, fungerar perfekt på alla samlingar:
(reduce + '(1 2 3))
;;=> 6
(reduce + [1 2 3])
;;=> 6
(reduce + #{1 2 3})
;;=> 6
Det andra skälet till att sekvenser är användbara är att eftersom de inte kräver någon speciell implementering av first
och rest
, tillåter de lata sekvenser vars element först realiseras när det är nödvändigt.
Med tanke på ett uttryck som skulle skapa en sekvens kan du linda in det uttrycket i det lazy-seq
makroet för att få ett objekt som fungerar som en sekvens, men kommer bara faktiskt att utvärdera det uttrycket när det uppmanas att göra det med seq
funktionen, vid vilken punkt det cachar resultatet av uttrycket och vidarebefordrar first
och rest
samtal till det cachade resultatet.
För ändliga sekvenser fungerar en lat sekvens vanligtvis på samma sätt som en ekvivalent ivrig sekvens:
(seq [:foo :bar])
;;=> (:foo :bar)
(lazy-seq [:foo :bar])
;;=> (:foo :bar)
Skillnaden blir emellertid uppenbar för oändliga sekvenser:
(defn eager-fibonacci [a b]
(cons a (eager-fibonacci b (+' a b))))
(defn lazy-fibonacci [a b]
(lazy-seq (cons a (lazy-fibonacci b (+' a b)))))
(take 10 (eager-fibonacci 0 1))
;; java.lang.StackOverflowError:
(take 10 (lazy-fibonacci 0 1))
;;=> (0 1 1 2 3 5 8 13 21 34)
vektorer
En vektor betecknas med fyrkantiga parenteser:
[]
;;=> []
[:foo]
;;=> [:foo]
[:foo :bar]
;;=> [:foo :bar]
[1 (+ 1 1) 3]
;;=> [1 2 3]
Förutom att använda den bokstavliga syntaxen kan du också använda vector
att konstruera en vektor:
(vector)
;;=> []
(vector :foo)
;;=> [:foo]
(vector :foo :bar)
;;=> [:foo :bar]
(vector 1 (+ 1 1) 3)
;;=> [1 2 3]
Du kan testa om något är en vektor med vector?
predikat:
(vector? [])
;;=> true
(vector? [:foo :bar])
;;=> true
(vector? nil)
;;=> false
(vector? 42)
;;=> false
(vector? :foo)
;;=> false
conj
lägger till element i slutet av en vektor:
(conj [] :foo)
;;=> [:foo]
(conj (conj [] :foo) :bar)
;;=> [:foo :bar]
(conj [] :foo :bar)
;;=> [:foo :bar]
count
ger antalet objekt i konstant tid:
(count [])
;;=> 0
(count (conj [] :foo))
;;=> 1
(count [:foo :bar])
;;=> 2
Du kan få det sista elementet i en vektor med peek
:
(peek [])
;;=> nil
(peek [:foo])
;;=> :foo
(peek [:foo :bar])
;;=> :bar
Du kan få en ny vektor utan det sista elementet med pop
:
(pop [:foo])
;;=> []
(pop [:foo :bar])
;;=> [:foo]
Observera att om du försöker poppa en tom vektor, får du en IllegalStateException
:
(pop [])
;; java.lang.IllegalStateException: Can't pop empty vector
Till skillnad från listor indexeras vektorer. Du kan få ett element i en vektor efter index i "konstant" tid med hjälp av get
:
(get [:foo :bar] 0)
;;=> :foo
(get [:foo :bar] 1)
;;=> :bar
(get [:foo :bar] -1)
;;=> nil
(get [:foo :bar] 2)
;;=> nil
Dessutom är vektorer själva funktioner som tar ett index och returnerar elementet vid det indexet:
([:foo :bar] 0)
;;=> :foo
([:foo :bar] 1)
;;=> :bar
Men om du kallar en vektor med ett ogiltigt index får du ett IndexOutOfBoundsException
istället för nil
:
([:foo :bar] -1)
;; java.lang.IndexOutOfBoundsException:
([:foo :bar] 2)
;; java.lang.IndexOutOfBoundsException:
Du kan få en ny vektor med ett annat värde vid ett visst index med hjälp av assoc
:
(assoc [:foo :bar] 0 42)
;;=> [42 :bar]
(assoc [:foo :bar] 1 42)
;;=> [:foo 42]
Om du skickar ett index lika med count
av vektorn kommer Clojure lägga elementet som om du hade använt conj
. Men om du klarar ett index som är negativt eller högre än count
får du ett IndexOutOfBoundsException
:
(assoc [:foo :bar] 2 42)
;;=> [:foo :bar 42]
(assoc [:foo :bar] -1 42)
;; java.lang.IndexOutOfBoundsException:
(assoc [:foo :bar] 3 42)
;; java.lang.IndexOutOfBoundsException:
Du kan få en sekvens av objekten i en vektor med hjälp av seq
:
(seq [])
;;=> nil
(seq [:foo])
;;=> (:foo)
(seq [:foo :bar])
;;=> (:foo :bar)
Eftersom vektorer är indexerade kan du också få en omvänd sekvens av en rseq
objekt med hjälp av rseq
:
(rseq [])
;;=> nil
(rseq [:foo])
;;=> (:foo)
(rseq [:foo :bar])
;;=> (:bar :foo)
Observera att även om alla listor är sekvenser och sekvenser visas på samma sätt som listor, är inte alla sekvenser listor!
'(:foo :bar)
;;=> (:foo :bar)
(seq [:foo :bar])
;;=> (:foo :bar)
(list? '(:foo :bar))
;;=> true
(list? (seq [:foo :bar]))
;;=> false
(list? (rseq [:foo :bar]))
;;=> false
Ställer
Liksom kartor är uppsättningar associerande och oordnade. Till skillnad från kartor, som innehåller mappningar från nycklar till värden, uppsätter i huvudsak kart från nycklar till sig själva.
En uppsättning betecknas med lockiga hängslen som föregås av en oktorporpe:
#{}
;;=> #{}
#{:foo}
;;=> #{:foo}
#{:foo :bar}
;;=> #{:bar :foo}
Liksom med kartor spelar ingen roll i vilken ordning elementen visas i en bokstavlig uppsättning:
(= #{:foo :bar} #{:bar :foo})
;;=> true
Du kan testa om något är en uppsättning med hjälp av set?
predikat:
(set? #{})
;;=> true
(set? #{:foo})
;;=> true
(set? #{:foo :bar})
;;=> true
(set? nil)
;;=> false
(set? 42)
;;=> false
(set? :foo)
;;=> false
Du kan testa om en karta innehåller ett visst objekt i "konstant" tid med hjälp av contains?
predikat:
(contains? #{} :foo)
;;=> false
(contains? #{:foo} :foo)
;;=> true
(contains? #{:foo} :bar)
;;=> false
(contains? #{} nil)
;;=> false
(contains? #{nil} nil)
;;=> true
Dessutom är uppsättningarna själva funktioner som tar ett element och returnerar det elementet om det finns i uppsättningen, eller nil
om det inte är:
(#{} :foo)
;;=> nil
(#{:foo} :foo)
;;=> :foo
(#{:foo} :bar)
;;=> nil
(#{} nil)
;;=> nil
(#{nil} nil)
;;=> nil
Du kan använda conj
att få en uppsättning som har alla element i en befintlig uppsättning, plus ett ytterligare objekt:
(conj #{} :foo)
;;=> #{:foo}
(conj (conj #{} :foo) :bar)
;;=> #{:bar :foo}
(conj #{:foo} :foo)
;;=> #{:foo}
Du kan använda disj
att få en uppsättning som har alla element i en befintlig uppsättning minus ett objekt:
(disj #{} :foo)
;;=> #{}
(disj #{:foo} :foo)
;;=> #{}
(disj #{:foo} :bar)
;;=> #{:foo}
(disj #{:foo :bar} :foo)
;;=> #{:bar}
(disj #{:foo :bar} :bar)
;;=> #{:foo}
count
ger antalet element i konstant tid:
(count #{})
;;=> 0
(count (conj #{} :foo))
;;=> 1
(count #{:foo :bar})
;;=> 2
Du kan få en sekvens av alla element i en uppsättning med seq
:
(seq #{})
;;=> nil
(seq #{:foo})
;;=> (:foo)
(seq #{:foo :bar})
;;=> (:bar :foo)
Kartor
Till skillnad från listan, som är en sekventiell datastruktur, och vektorn, som är både sekventiell och associativ, är kartan uteslutande en associativ datastruktur. En karta består av en uppsättning kartläggningar från nycklar till värden. Alla nycklar är unika, så kartor stöder "konstant" uppslag från tid till nycklar till värden.
En karta betecknas med lockiga hängslen:
{}
;;=> {}
{:foo :bar}
;;=> {:foo :bar}
{:foo :bar :baz :qux}
;;=> {:foo :bar, :baz :qux}
Varje par av två element är ett nyckelvärdespar. Så till exempel har den första kartan ovan inga mappningar. Den andra har en kartläggning, från nyckeln :foo
till värdet :bar
. Den tredje har två mappningar, en från nyckeln :foo
till värdet :bar
, och en från nyckeln :baz
till värdet :qux
. Kartor är i sig ordenade, så ordningen i vilken kartläggningarna visas spelar ingen roll:
(= {:foo :bar :baz :qux}
{:baz :qux :foo :bar})
;;=> true
Du kan testa om något är en karta med map?
predikat:
(map? {})
;;=> true
(map? {:foo :bar})
;;=> true
(map? {:foo :bar :baz :qux})
;;=> true
(map? nil)
;;=> false
(map? 42)
;;=> false
(map? :foo)
;;=> false
Du kan testa om en karta innehåller en given nyckel i "konstant" tid med hjälp av contains?
predikat:
(contains? {:foo :bar :baz :qux} 42)
;;=> false
(contains? {:foo :bar :baz :qux} :foo)
;;=> true
(contains? {:foo :bar :baz :qux} :bar)
;;=> false
(contains? {:foo :bar :baz :qux} :baz)
;;=> true
(contains? {:foo :bar :baz :qux} :qux)
;;=> false
(contains? {:foo nil} :foo)
;;=> true
(contains? {:foo nil} :bar)
;;=> false
Du kan få värdet associerat med en nyckel med hjälp av get
:
(get {:foo :bar :baz :qux} 42)
;;=> nil
(get {:foo :bar :baz :qux} :foo)
;;=> :bar
(get {:foo :bar :baz :qux} :bar)
;;=> nil
(get {:foo :bar :baz :qux} :baz)
;;=> :qux
(get {:foo :bar :baz :qux} :qux)
;;=> nil
(get {:foo nil} :foo)
;;=> nil
(get {:foo nil} :bar)
;;=> nil
Dessutom är kartorna själva funktioner som tar en nyckel och returnerar värdet som är associerat med den tangenten:
({:foo :bar :baz :qux} 42)
;;=> nil
({:foo :bar :baz :qux} :foo)
;;=> :bar
({:foo :bar :baz :qux} :bar)
;;=> nil
({:foo :bar :baz :qux} :baz)
;;=> :qux
({:foo :bar :baz :qux} :qux)
;;=> nil
({:foo nil} :foo)
;;=> nil
({:foo nil} :bar)
;;=> nil
Du kan få en hel kartpost (nyckel och värde tillsammans) som en tvåelementvektor genom att find
:
(find {:foo :bar :baz :qux} 42)
;;=> nil
(find {:foo :bar :baz :qux} :foo)
;;=> [:foo :bar]
(find {:foo :bar :baz :qux} :bar)
;;=> nil
(find {:foo :bar :baz :qux} :baz)
;;=> [:baz :qux]
(find {:foo :bar :baz :qux} :qux)
;;=> nil
(find {:foo nil} :foo)
;;=> [:foo nil]
(find {:foo nil} :bar)
;;=> nil
Du kan extrahera nyckeln eller värdet från en kartpost med hjälp av key
respektive val
:
(key (find {:foo :bar} :foo))
;;=> :foo
(val (find {:foo :bar} :foo))
;;=> :bar
Observera att även om alla Clojure-kartposter är vektorer, är inte alla vektorer kartposter. Om du försöker ringa key
eller val
på något som inte är en kartpost, får du en ClassCastException
:
(key [:foo :bar])
;; java.lang.ClassCastException:
(val [:foo :bar])
;; java.lang.ClassCastException:
Du kan testa om något är en kartpost med hjälp av map-entry?
predikat:
(map-entry? (find {:foo :bar} :foo))
;;=> true
(map-entry? [:foo :bar])
;;=> false
Du kan använda assoc
att få en karta som har alla samma nyckelvärdespar som en befintlig karta, med en mappning tillagd eller ändrad:
(assoc {} :foo :bar)
;;=> {:foo :bar}
(assoc (assoc {} :foo :bar) :baz :qux)
;;=> {:foo :bar, :baz :qux}
(assoc {:baz :qux} :foo :bar)
;;=> {:baz :qux, :foo :bar}
(assoc {:foo :bar :baz :qux} :foo 42)
;;=> {:foo 42, :baz :qux}
(assoc {:foo :bar :baz :qux} :baz 42)
;;=> {:foo :bar, :baz 42}
Du kan använda dissoc
att få en karta som har alla samma nyckelvärdespar som en befintlig karta, med eventuellt en kartläggning bort:
(dissoc {:foo :bar :baz :qux} 42)
;;=> {:foo :bar :baz :qux}
(dissoc {:foo :bar :baz :qux} :foo)
;;=> {:baz :qux}
(dissoc {:foo :bar :baz :qux} :bar)
;;=> {:foo :bar :baz :qux}
(dissoc {:foo :bar :baz :qux} :baz)
;;=> {:foo :bar}
(dissoc {:foo :bar :baz :qux} :qux)
;;=> {:foo :bar :baz :qux}
(dissoc {:foo nil} :foo)
;;=> {}
count
ger antalet kartläggningar, i konstant tid:
(count {})
;;=> 0
(count (assoc {} :foo :bar))
;;=> 1
(count {:foo :bar :baz :qux})
;;=> 2
Du kan få en sekvens av alla poster på en karta med seq
:
(seq {})
;;=> nil
(seq {:foo :bar})
;;=> ([:foo :bar])
(seq {:foo :bar :baz :qux})
;;=> ([:foo :bar] [:baz :qux])
Återigen är kartor oordnade, så beställningen av objekten i en sekvens som du får genom att ringa seq
på en karta är odefinierad.
Du kan få en sekvens av bara tangenterna eller bara värdena på en karta med hjälp av keys
respektive vals
:
(keys {})
;;=> nil
(keys {:foo :bar})
;;=> (:foo)
(keys {:foo :bar :baz :qux})
;;=> (:foo :baz)
(vals {})
;;=> nil
(vals {:foo :bar})
;;=> (:bar)
(vals {:foo :bar :baz :qux})
;;=> (:bar :qux)
Clojure 1.9 lägger till en bokstavlig syntax för att mer kortfattat representerar en karta där tangenterna delar samma namnutrymme. Observera att kartan i båda fallen är identisk (kartan "känner inte" standardnamnområdet), detta är bara en syntaktisk bekvämlighet.
;; typical map syntax
(def p {:person/first"Darth" :person/last "Vader" :person/email "[email protected]"})
;; namespace map literal syntax
(def p #:person{:first "Darth" :last "Vader" :email "[email protected]"})