clojure
Collecties en reeksen
Zoeken…
Syntaxis
-
'()
→()
-
'(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"}
(vermeldingen worden per sleutel gesorteerd als ze als een reeks worden gebruikt) -
#{}
→#{}
-
#{1 2 3 4 5}
→#{4 3 2 5 1}
(ongeordend) -
(
hash-set
1 2 3 4 5)
→#{2 5 4 1 3}
(ongeordend) -
(
sorted-set
2 5 4 3 1)
→#{1 2 3 4 5}
collecties
Alle ingebouwde Clojure-collecties zijn onveranderlijk en heterogeen, hebben een letterlijke syntaxis en ondersteunen de conj
, count
en seq
functies.
-
conj
retourneert een nieuwe collectie die equivalent is aan een bestaande collectie met een item "toegevoegd", in "constante" of logaritmische tijd. Wat dit precies betekent, hangt af van de collectie. -
count
retourneert het aantal items in een verzameling, in constante tijd. -
seq
retourneertnil
voor een lege verzameling, of een reeks items voor een niet-lege verzameling, in constante tijd.
lijsten
Een lijst wordt tussen haakjes aangegeven:
()
;;=> ()
Een Clojure-lijst is een afzonderlijk gekoppelde lijst . conj
"verbindt" een nieuw element met de verzameling op de meest efficiënte locatie. Voor lijsten is dit aan het begin:
(conj () :foo)
;;=> (:foo)
(conj (conj () :bar) :foo)
;;=> (:foo :bar)
In tegenstelling tot andere collecties worden niet-lege lijsten geëvalueerd als aanroepen naar speciale formulieren, macro's of functies wanneer ze worden geëvalueerd. Terwijl (:foo)
dus de letterlijke weergave is van de lijst met :foo
als het enige item, zal het evalueren van (:foo)
in een REPL ertoe leiden dat een IllegalArgumentException
wordt gegenereerd omdat een trefwoord niet als een nullary-functie kan worden opgeroepen.
(:foo)
;; java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :foo
Om te voorkomen dat Clojure een niet-lege lijst evalueert, kunt u deze quote
:
'(:foo)
;;=> (:foo)
'(:foo :bar)
;;=> (:foo :bar)
Helaas worden hierdoor de elementen niet geëvalueerd:
(+ 1 1)
;;=> 2
'(1 (+ 1 1) 3)
;;=> (1 (+ 1 1) 3)
Om deze reden wilt u meestal list
, een variadische functie die alle argumenten evalueert en die resultaten gebruikt om een lijst samen te stellen:
(list)
;;=> ()
(list :foo)
;;=> (:foo)
(list :foo :bar)
;;=> (:foo :bar)
(list 1 (+ 1 1) 3)
;;=> (1 2 3)
count
geeft het aantal items terug, in constante tijd:
(count ())
;;=> 0
(count (conj () :foo))
;;=> 1
(count '(:foo :bar))
;;=> 2
U kunt testen of iets een lijst is met behulp van de list?
predikaat:
(list? ())
;;=> true
(list? '(:foo :bar))
;;=> true
(list? nil)
;;=> false
(list? 42)
;;=> false
(list? :foo)
;;=> false
U kunt het eerste element van een lijst krijgen met behulp van peek
:
(peek ())
;;=> nil
(peek '(:foo))
;;=> :foo
(peek '(:foo :bar))
;;=> :foo
U kunt een nieuwe lijst krijgen zonder het eerste element met behulp van pop
:
(pop '(:foo))
;;=> ()
(pop '(:foo :bar))
;;=> (:bar)
Merk op dat als u probeert om pop
een lege lijst, krijg je een te krijgen IllegalStateException
:
(pop ())
;; java.lang.IllegalStateException: Can't pop empty list
Ten slotte zijn alle lijsten reeksen, dus u kunt alles doen met een lijst die u met elke andere reeks kunt doen. Inderdaad, met uitzondering van de lege lijst, retourneert seq
op een lijst exact hetzelfde object:
(seq ())
;;=> nil
(seq '(:foo))
;;=> (:foo)
(seq '(:foo :bar))
;;=> (:foo :bar)
(let [x '(:foo :bar)]
(identical? x (seq x)))
;;=> true
Opeenvolgingen
Een reeks lijkt erg op een lijst: het is een onveranderlijk object dat u in constante tijd het first
element of de rest
van de elementen kan geven. U kunt ook cons
truct een nieuwe reeks van een bestaande reeks en een item dat stok bij het begin.
Je kunt testen of iets een reeks is met behulp van de seq?
predikaat:
(seq? nil)
;;=> false
(seq? 42)
;;=> false
(seq? :foo)
;;=> false
Zoals u al weet, zijn lijsten reeksen:
(seq? ())
;;=> true
(seq? '(:foo :bar))
;;=> true
Alles wat je krijgt door seq
of rseq
of keys
of vals
op een niet-lege verzameling aan te roepen, is ook een reeks:
(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
Onthoud dat alle lijsten reeksen zijn, maar niet alle reeksen lijsten zijn. Hoewel lijsten peek
en pop
en in constante tijd count
, hoeft een reeks over het algemeen geen van deze functies te ondersteunen. Als u probeert te bellen peek
of pop
op een sequentie die ook niet Clojure's stack-interface ondersteunt, dan heb je een te krijgen 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
Als u count
oproept in een reeks die count
in constante tijd implementeert, krijgt u geen foutmelding; in plaats daarvan zal Clojure de hele reeks doorlopen totdat deze het einde bereikt, en vervolgens het aantal elementen teruggeven dat het heeft doorlopen. Dit betekent dat voor algemene sequenties de count
lineair is, niet constant, de tijd. U kunt testen of iets constant-time count
met behulp van de counted?
predikaat:
(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
Zoals hierboven vermeld, kunt u first
gebruiken om het eerste element van een reeks te krijgen. Merk op dat first
seq
aangeroepen op hun argument, dus het kan worden gebruikt op alles wat "seqable" is, niet alleen werkelijke reeksen:
(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
Zoals hierboven vermeld, kunt u rest
gebruiken om een reeks te krijgen die alles behalve het eerste element van een bestaande reeks bevat. Zoals first
, roept het seq
op zijn argument. Het roept echter geen seq
op het resultaat! Dit betekent dat als je rest
in een reeks die minder dan twee items bevat, je terug ()
plaats van nil
:
(rest nil)
;;=> ()
(rest '(:foo))
;;=> ()
(rest '(:foo :bar))
;;=> (:bar)
(rest [:foo])
;;=> ()
(rest [:foo :bar])
;;=> (:bar)
(rest {:foo :bar})
;;=> ()
(rest #{:foo})
;;=> ()
Als je weer nil
wilt krijgen wanneer er geen elementen meer in een reeks zijn, kun je de next
plaats van de rest
:
(next nil)
;;=> nil
(next '(:foo))
;;=> nil
(next [:foo])
;;=> nil
Je kunt de functie cons
gebruiken om een nieuwe reeks te maken die het eerste argument voor het first
en het tweede argument voor de rest
retourneert:
(cons :foo nil)
;;=> (:foo)
(cons :foo (cons :bar nil))
;;=> (:foo :bar)
Clojure biedt een grote reeks bibliotheek met veel functies voor het omgaan met reeksen. Het belangrijkste van deze bibliotheek is dat deze werkt met alles "seqable", niet alleen lijsten. Daarom is het concept van een reeks zo nuttig; het betekent dat een enkele functie, zoals reduce
, perfect werkt bij elke verzameling:
(reduce + '(1 2 3))
;;=> 6
(reduce + [1 2 3])
;;=> 6
(reduce + #{1 2 3})
;;=> 6
De andere reden dat reeksen nuttig zijn, is dat, omdat ze geen specifieke implementatie van first
en rest
vereisen, ze luie reeksen toestaan waarvan de elementen alleen worden gerealiseerd wanneer dat nodig is.
Gegeven een uitdrukking die een reeks zou creëren, kunt u die uitdrukking in de lazy-seq
macro wikkelen om een object te krijgen dat als een reeks fungeert, maar die uitdrukking alleen daadwerkelijk evalueren wanneer het wordt gevraagd door de seq
functie, op welk punt het het resultaat van de uitdrukking in de cache opslaat en first
doorstuurt en de rest
aanroepen naar het in de cache opgeslagen resultaat.
Voor eindige reeksen werkt een luie reeks meestal hetzelfde als een vergelijkbare enthousiaste reeks:
(seq [:foo :bar])
;;=> (:foo :bar)
(lazy-seq [:foo :bar])
;;=> (:foo :bar)
Het verschil wordt echter duidelijk voor oneindige reeksen:
(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)
vectoren
Een vector wordt aangegeven met vierkante haken:
[]
;;=> []
[:foo]
;;=> [:foo]
[:foo :bar]
;;=> [:foo :bar]
[1 (+ 1 1) 3]
;;=> [1 2 3]
Naast de letterlijke syntaxis kunt u ook de vector
om een vector te construeren:
(vector)
;;=> []
(vector :foo)
;;=> [:foo]
(vector :foo :bar)
;;=> [:foo :bar]
(vector 1 (+ 1 1) 3)
;;=> [1 2 3]
U kunt testen of iets een vector is met behulp van de vector?
predikaat:
(vector? [])
;;=> true
(vector? [:foo :bar])
;;=> true
(vector? nil)
;;=> false
(vector? 42)
;;=> false
(vector? :foo)
;;=> false
conj
voegt elementen toe aan het einde van een vector:
(conj [] :foo)
;;=> [:foo]
(conj (conj [] :foo) :bar)
;;=> [:foo :bar]
(conj [] :foo :bar)
;;=> [:foo :bar]
count
geeft het aantal items terug, in constante tijd:
(count [])
;;=> 0
(count (conj [] :foo))
;;=> 1
(count [:foo :bar])
;;=> 2
Je kunt het laatste element van een vector krijgen met behulp van peek
:
(peek [])
;;=> nil
(peek [:foo])
;;=> :foo
(peek [:foo :bar])
;;=> :bar
Je kunt een nieuwe vector krijgen zonder het laatste element met behulp van pop
:
(pop [:foo])
;;=> []
(pop [:foo :bar])
;;=> [:foo]
Merk op dat als je probeert een lege vector te laten verschijnen, je een IllegalStateException
:
(pop [])
;; java.lang.IllegalStateException: Can't pop empty vector
In tegenstelling tot lijsten worden vectoren geïndexeerd. Je kunt een element van een vector per index krijgen in "constante" tijd met get
:
(get [:foo :bar] 0)
;;=> :foo
(get [:foo :bar] 1)
;;=> :bar
(get [:foo :bar] -1)
;;=> nil
(get [:foo :bar] 2)
;;=> nil
Bovendien zijn vectoren zelf functies die een index nemen en het element op die index teruggeven:
([:foo :bar] 0)
;;=> :foo
([:foo :bar] 1)
;;=> :bar
Als u echter een vector met een ongeldige index IndexOutOfBoundsException
, krijgt u een IndexOutOfBoundsException
plaats van nil
:
([:foo :bar] -1)
;; java.lang.IndexOutOfBoundsException:
([:foo :bar] 2)
;; java.lang.IndexOutOfBoundsException:
U kunt een nieuwe vector met een andere waarde op een bepaalde index krijgen met behulp van assoc
:
(assoc [:foo :bar] 0 42)
;;=> [42 :bar]
(assoc [:foo :bar] 1 42)
;;=> [:foo 42]
Als u een index doorgeeft die gelijk is aan het count
van de vector, voegt Clojure het element toe alsof u conj
had gebruikt. Als u echter een index doorgeeft die negatief of groter is dan de count
, krijgt u een 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:
Je kunt een reeks items in een vector krijgen met seq
:
(seq [])
;;=> nil
(seq [:foo])
;;=> (:foo)
(seq [:foo :bar])
;;=> (:foo :bar)
Omdat vectoren worden geïndexeerd, kunt u ook een omgekeerde volgorde van items van een vector krijgen met behulp van rseq
:
(rseq [])
;;=> nil
(rseq [:foo])
;;=> (:foo)
(rseq [:foo :bar])
;;=> (:bar :foo)
Hoewel alle lijsten reeksen zijn en reeksen op dezelfde manier worden weergegeven als lijsten, zijn niet alle reeksen lijsten!
'(:foo :bar)
;;=> (:foo :bar)
(seq [:foo :bar])
;;=> (:foo :bar)
(list? '(:foo :bar))
;;=> true
(list? (seq [:foo :bar]))
;;=> false
(list? (rseq [:foo :bar]))
;;=> false
sets
Net als kaarten zijn sets associatief en ongeordend. In tegenstelling tot kaarten, die toewijzingen van sleutels tot waarden bevatten, stelt de kaart in wezen de kaart in van sleutels tot zichzelf.
Een set wordt aangegeven met accolades voorafgegaan door een octothorpe:
#{}
;;=> #{}
#{:foo}
;;=> #{:foo}
#{:foo :bar}
;;=> #{:bar :foo}
Net als bij kaarten, maakt de volgorde waarin elementen in een letterlijke set verschijnen niet uit:
(= #{:foo :bar} #{:bar :foo})
;;=> true
U kunt testen of iets een set is met behulp van de set?
predikaat:
(set? #{})
;;=> true
(set? #{:foo})
;;=> true
(set? #{:foo :bar})
;;=> true
(set? nil)
;;=> false
(set? 42)
;;=> false
(set? :foo)
;;=> false
U kunt testen of een kaart een bepaald item in "constante" tijd contains?
met behulp van de contains?
predikaat:
(contains? #{} :foo)
;;=> false
(contains? #{:foo} :foo)
;;=> true
(contains? #{:foo} :bar)
;;=> false
(contains? #{} nil)
;;=> false
(contains? #{nil} nil)
;;=> true
Bovendien zijn sets zelf functies die een element nemen en dat element retourneren als het in de set aanwezig is, of nil
als het niet is:
(#{} :foo)
;;=> nil
(#{:foo} :foo)
;;=> :foo
(#{:foo} :bar)
;;=> nil
(#{} nil)
;;=> nil
(#{nil} nil)
;;=> nil
Je kunt conj
gebruiken om een set te krijgen die alle elementen van een bestaande set bevat, plus een extra item:
(conj #{} :foo)
;;=> #{:foo}
(conj (conj #{} :foo) :bar)
;;=> #{:bar :foo}
(conj #{:foo} :foo)
;;=> #{:foo}
Je kunt disj
gebruiken om een set te krijgen die alle elementen van een bestaande set bevat, min één item:
(disj #{} :foo)
;;=> #{}
(disj #{:foo} :foo)
;;=> #{}
(disj #{:foo} :bar)
;;=> #{:foo}
(disj #{:foo :bar} :foo)
;;=> #{:bar}
(disj #{:foo :bar} :bar)
;;=> #{:foo}
count
geeft het aantal elementen terug, in constante tijd:
(count #{})
;;=> 0
(count (conj #{} :foo))
;;=> 1
(count #{:foo :bar})
;;=> 2
Je kunt een reeks van alle elementen in een set krijgen met seq
:
(seq #{})
;;=> nil
(seq #{:foo})
;;=> (:foo)
(seq #{:foo :bar})
;;=> (:bar :foo)
Kaarten
In tegenstelling tot de lijst, die een sequentiële datastructuur is, en de vector, die zowel sequentieel als associatief is, is de kaart uitsluitend een associatieve datastructuur. Een kaart bestaat uit een reeks toewijzingen van sleutels tot waarden. Alle sleutels zijn uniek, dus kaarten ondersteunen het "constant" zoeken van sleutels naar waarden.
Een kaart wordt aangegeven met accolades:
{}
;;=> {}
{:foo :bar}
;;=> {:foo :bar}
{:foo :bar :baz :qux}
;;=> {:foo :bar, :baz :qux}
Elk paar van twee elementen is een sleutel / waarde-paar. De eerste kaart hierboven heeft bijvoorbeeld geen toewijzingen. De tweede heeft één afbeelding, van de sleutel :foo
tot de waarde :bar
. De derde heeft twee toewijzingen, een van de sleutel :foo
tot de waarde :bar
en een van de sleutel :baz
tot de waarde :qux
. Kaarten zijn inherent ongeordend, dus de volgorde waarin de toewijzingen worden weergegeven, doet er niet toe:
(= {:foo :bar :baz :qux}
{:baz :qux :foo :bar})
;;=> true
U kunt testen of iets een kaart is met behulp van de map?
predikaat:
(map? {})
;;=> true
(map? {:foo :bar})
;;=> true
(map? {:foo :bar :baz :qux})
;;=> true
(map? nil)
;;=> false
(map? 42)
;;=> false
(map? :foo)
;;=> false
U kunt testen of een kaart een gegeven sleutel in "constante" tijd contains?
met behulp van de contains?
predikaat:
(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
U kunt de waarde krijgen die aan een sleutel is gekoppeld met 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
Bovendien zijn kaarten zelf functies die een sleutel gebruiken en de waarde retourneren die aan die sleutel is gekoppeld:
({: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
U kunt een volledig kaartitem (sleutel en waarde samen) krijgen als een vector met twee elementen met behulp van 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
U kunt de sleutel of waarde uit een kaartitem extraheren met respectievelijk key
of val
:
(key (find {:foo :bar} :foo))
;;=> :foo
(val (find {:foo :bar} :foo))
;;=> :bar
Merk op dat, hoewel alle Clojure-kaartitems vectoren zijn, niet alle vectoren kaartitems zijn. Als u key
of val
probeert aan te roepen op iets dat geen ClassCastException
, krijgt u een ClassCastException
:
(key [:foo :bar])
;; java.lang.ClassCastException:
(val [:foo :bar])
;; java.lang.ClassCastException:
U kunt testen of iets een kaartinvoer is met behulp van de map-entry?
predikaat:
(map-entry? (find {:foo :bar} :foo))
;;=> true
(map-entry? [:foo :bar])
;;=> false
U kunt assoc
gebruiken om een kaart te krijgen die allemaal dezelfde sleutel / waarde-paren heeft als een bestaande kaart, met één toewijzing toegevoegd of gewijzigd:
(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}
Je kunt dissoc
gebruiken om een kaart te krijgen die allemaal dezelfde sleutel / waarde-paren heeft als een bestaande kaart, met mogelijk één kaart verwijderd:
(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
geeft het aantal toewijzingen terug, in constante tijd:
(count {})
;;=> 0
(count (assoc {} :foo :bar))
;;=> 1
(count {:foo :bar :baz :qux})
;;=> 2
U kunt een reeks van alle vermeldingen op een kaart krijgen met seq
:
(seq {})
;;=> nil
(seq {:foo :bar})
;;=> ([:foo :bar])
(seq {:foo :bar :baz :qux})
;;=> ([:foo :bar] [:baz :qux])
Nogmaals, kaarten zijn niet geordend, dus de volgorde van de items in een reeks die u krijgt door seq
op een kaart te bellen, is niet gedefinieerd.
U kunt een reeks van alleen de toetsen of alleen de waarden in een kaart krijgen met behulp van keys
of vals
, respectievelijk:
(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 voegt een letterlijke syntaxis toe voor een meer beknopte weergave van een kaart waarbij de toetsen dezelfde naamruimte delen. Merk op dat de kaart in beide gevallen identiek is (de kaart "kent" de standaardnaamruimte niet), dit is slechts een syntactisch gemak.
;; 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]"})