clojure
Collections et séquences
Recherche…
Syntaxe
-
'()
→()
-
'(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"}
(les entrées sont triées par clé lorsqu'elles sont utilisées comme une séquence) -
#{}
→#{}
-
#{1 2 3 4 5}
→#{4 3 2 5 1}
(non ordonné) -
(
hash-set
1 2 3 4 5)
→#{2 5 4 1 3}
(non ordonné) -
(
sorted-set
2 5 4 3 1)
→#{1 2 3 4 5}
Collections
Toutes les collections Clojure intégrées sont immuables et hétérogènes, ont une syntaxe littérale et prennent en charge les fonctions conj
, count
et seq
.
-
conj
renvoie une nouvelle collection équivalente à une collection existante avec un élément "ajouté", soit dans le temps "constant" ou logarithmique. Ce que cela signifie exactement dépend de la collection. -
count
renvoie le nombre d'éléments d'une collection, en temps constant. -
seq
renvoienil
pour une collection vide ou une séquence d'éléments pour une collection non vide, à temps constant.
Des listes
Une liste est indiquée par des parenthèses:
()
;;=> ()
Une liste de Clojure est une liste à liens simples . conj
"joint" un nouvel élément à la collection dans l'emplacement le plus efficace. Pour les listes, c'est au début:
(conj () :foo)
;;=> (:foo)
(conj (conj () :bar) :foo)
;;=> (:foo :bar)
Contrairement aux autres collections, les listes non vides sont évaluées comme des appels à des formulaires, macros ou fonctions spéciaux lorsqu'elles sont évaluées. Par conséquent, tant que (:foo)
est la représentation littérale de la liste contenant :foo
comme seul élément, l'évaluation de (:foo)
dans une REPL provoquera une IllegalArgumentException
car un mot clé ne peut pas être appelé comme fonction nullary .
(:foo)
;; java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :foo
Pour empêcher Clojure d’évaluer une liste non vide, vous pouvez la quote
:
'(:foo)
;;=> (:foo)
'(:foo :bar)
;;=> (:foo :bar)
Malheureusement, les éléments ne sont pas évalués:
(+ 1 1)
;;=> 2
'(1 (+ 1 1) 3)
;;=> (1 (+ 1 1) 3)
Pour cette raison, vous voudrez généralement utiliser list
, une fonction variadic qui évalue tous ses arguments et utilise ces résultats pour construire une liste:
(list)
;;=> ()
(list :foo)
;;=> (:foo)
(list :foo :bar)
;;=> (:foo :bar)
(list 1 (+ 1 1) 3)
;;=> (1 2 3)
count
renvoie le nombre d'éléments, en temps constant:
(count ())
;;=> 0
(count (conj () :foo))
;;=> 1
(count '(:foo :bar))
;;=> 2
Vous pouvez tester si quelque chose est une liste en utilisant la list?
prédicat:
(list? ())
;;=> true
(list? '(:foo :bar))
;;=> true
(list? nil)
;;=> false
(list? 42)
;;=> false
(list? :foo)
;;=> false
Vous pouvez obtenir le premier élément d'une liste en utilisant peek
:
(peek ())
;;=> nil
(peek '(:foo))
;;=> :foo
(peek '(:foo :bar))
;;=> :foo
Vous pouvez obtenir une nouvelle liste sans le premier élément en utilisant pop
:
(pop '(:foo))
;;=> ()
(pop '(:foo :bar))
;;=> (:bar)
Notez que si vous essayez de faire pop
une liste vide, vous obtiendrez une IllegalStateException
:
(pop ())
;; java.lang.IllegalStateException: Can't pop empty list
Enfin, toutes les listes sont des séquences, vous pouvez donc tout faire avec une liste que vous pouvez faire avec toute autre séquence. En effet, à l'exception de la liste vide, l'appel de seq
sur une liste renvoie exactement le même objet:
(seq ())
;;=> nil
(seq '(:foo))
;;=> (:foo)
(seq '(:foo :bar))
;;=> (:foo :bar)
(let [x '(:foo :bar)]
(identical? x (seq x)))
;;=> true
Séquences
Une séquence ressemble beaucoup à une liste: c'est un objet immuable qui peut vous donner son first
élément ou le rest
de ses éléments en temps constant. Vous pouvez également cons
truct une nouvelle séquence d'une séquence existante et un élément de coller au début.
Vous pouvez tester si quelque chose est une séquence en utilisant le seq?
prédicat:
(seq? nil)
;;=> false
(seq? 42)
;;=> false
(seq? :foo)
;;=> false
Comme vous le savez déjà, les listes sont des séquences:
(seq? ())
;;=> true
(seq? '(:foo :bar))
;;=> true
Tout ce que vous obtenez en appelant seq
ou rseq
ou des keys
ou des vals
sur une collection non vide est également une séquence:
(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
Rappelez-vous que toutes les listes sont des séquences, mais toutes les séquences ne sont pas des listes. Alors que les listes prennent en charge les fonctions de peek
et de pop
et count
en temps constant, en général, une séquence n'a pas besoin de prendre en charge l'une de ces fonctions. Si vous essayez d'appeler peek
ou pop
sur une séquence qui ne prend pas également en charge l'interface de pile de Clojure, vous obtiendrez une 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
Si vous appelez count
sur une séquence qui n'implémente pas le count
en temps constant, vous n'obtiendrez pas d'erreur. Clojure traversera toute la séquence jusqu'à la fin, puis retournera le nombre d'éléments qu'il a parcourus. Cela signifie que, pour les séquences générales, le count
est linéaire, pas constant, le temps. Vous pouvez tester si quelque chose prend en charge le count
temps constant en utilisant le counted?
prédicat:
(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
Comme mentionné ci-dessus, vous pouvez utiliser d' first
pour obtenir le premier élément d'une séquence. Notez que le first
appelera seq
sur leur argument, donc il peut être utilisé sur tout "seqable", pas seulement sur les séquences réelles:
(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
Comme mentionné ci-dessus, vous pouvez utiliser rest
pour obtenir une séquence contenant tous les éléments sauf le premier élément d'une séquence existante. Comme first
, il appelle seq
sur son argument. Cependant, il n'appelle pas seq
sur son résultat! Cela signifie que si vous appelez rest
sur une séquence contenant moins de deux éléments, vous récupérerez ()
au lieu de nil
:
(rest nil)
;;=> ()
(rest '(:foo))
;;=> ()
(rest '(:foo :bar))
;;=> (:bar)
(rest [:foo])
;;=> ()
(rest [:foo :bar])
;;=> (:bar)
(rest {:foo :bar})
;;=> ()
(rest #{:foo})
;;=> ()
Si vous voulez récupérer nil
quand il n'y a plus d'éléments dans une séquence, vous pouvez utiliser next
au lieu de rest
:
(next nil)
;;=> nil
(next '(:foo))
;;=> nil
(next [:foo])
;;=> nil
Vous pouvez utiliser la fonction cons
pour créer une nouvelle séquence qui renverra son premier argument pour le first
et son deuxième argument pour le rest
:
(cons :foo nil)
;;=> (:foo)
(cons :foo (cons :bar nil))
;;=> (:foo :bar)
Clojure fournit une grande bibliothèque de séquences avec de nombreuses fonctions pour gérer les séquences. L'important à propos de cette bibliothèque est qu'elle fonctionne avec tout ce qui peut être "séqé", pas seulement les listes. C'est pourquoi le concept d'une séquence est si utile; cela signifie qu'une seule fonction, comme reduce
, fonctionne parfaitement sur n'importe quelle collection:
(reduce + '(1 2 3))
;;=> 6
(reduce + [1 2 3])
;;=> 6
(reduce + #{1 2 3})
;;=> 6
L'autre raison pour laquelle les séquences sont utiles est que, puisqu'elles ne requièrent aucune implémentation particulière du first
et du rest
, elles permettent des séquences paresseuses dont les éléments ne sont réalisés que lorsque cela est nécessaire.
Étant donné une expression qui créerait une séquence, vous pouvez envelopper cette expression dans la macro lazy-seq
pour obtenir un objet qui agit comme une séquence, mais n'évaluera réellement cette expression que lorsque la fonction seq
le demandera, à quel point il va mettre en cache le résultat de l'expression et en avant first
et rest
les appels vers le résultat mis en cache.
Pour les séquences finies, une séquence paresseuse agit généralement comme une séquence équivalente:
(seq [:foo :bar])
;;=> (:foo :bar)
(lazy-seq [:foo :bar])
;;=> (:foo :bar)
Cependant, la différence devient évidente pour des séquences infinies:
(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)
Vecteurs
Un vecteur est indiqué par des crochets:
[]
;;=> []
[:foo]
;;=> [:foo]
[:foo :bar]
;;=> [:foo :bar]
[1 (+ 1 1) 3]
;;=> [1 2 3]
En plus de la syntaxe littérale, vous pouvez également utiliser la fonction vector
pour construire un vecteur:
(vector)
;;=> []
(vector :foo)
;;=> [:foo]
(vector :foo :bar)
;;=> [:foo :bar]
(vector 1 (+ 1 1) 3)
;;=> [1 2 3]
Vous pouvez tester si quelque chose est un vecteur en utilisant le vector?
prédicat:
(vector? [])
;;=> true
(vector? [:foo :bar])
;;=> true
(vector? nil)
;;=> false
(vector? 42)
;;=> false
(vector? :foo)
;;=> false
conj
ajoute des éléments à la fin d'un vecteur:
(conj [] :foo)
;;=> [:foo]
(conj (conj [] :foo) :bar)
;;=> [:foo :bar]
(conj [] :foo :bar)
;;=> [:foo :bar]
count
renvoie le nombre d'éléments, en temps constant:
(count [])
;;=> 0
(count (conj [] :foo))
;;=> 1
(count [:foo :bar])
;;=> 2
Vous pouvez obtenir le dernier élément d'un vecteur en utilisant peek
:
(peek [])
;;=> nil
(peek [:foo])
;;=> :foo
(peek [:foo :bar])
;;=> :bar
Vous pouvez obtenir un nouveau vecteur sans le dernier élément en utilisant pop
:
(pop [:foo])
;;=> []
(pop [:foo :bar])
;;=> [:foo]
Notez que si vous essayez de faire apparaître un vecteur vide, vous obtiendrez une IllegalStateException
:
(pop [])
;; java.lang.IllegalStateException: Can't pop empty vector
Contrairement aux listes, les vecteurs sont indexés. Vous pouvez obtenir un élément d'un vecteur par index dans le temps "constant" en utilisant get
:
(get [:foo :bar] 0)
;;=> :foo
(get [:foo :bar] 1)
;;=> :bar
(get [:foo :bar] -1)
;;=> nil
(get [:foo :bar] 2)
;;=> nil
De plus, les vecteurs eux-mêmes sont des fonctions qui prennent un index et renvoient l'élément à cet index:
([:foo :bar] 0)
;;=> :foo
([:foo :bar] 1)
;;=> :bar
Cependant, si vous appelez un vecteur avec un index non valide, vous obtiendrez une IndexOutOfBoundsException
au lieu de nil
:
([:foo :bar] -1)
;; java.lang.IndexOutOfBoundsException:
([:foo :bar] 2)
;; java.lang.IndexOutOfBoundsException:
Vous pouvez obtenir un nouveau vecteur avec une valeur différente à un index particulier en utilisant assoc
:
(assoc [:foo :bar] 0 42)
;;=> [42 :bar]
(assoc [:foo :bar] 1 42)
;;=> [:foo 42]
Si vous passez un index égal au count
de vecteurs, Clojure ajoutera l'élément comme si vous aviez utilisé conj
. Toutefois, si vous transmettez un index négatif ou supérieur au count
, vous obtenez une 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:
Vous pouvez obtenir une séquence des éléments dans un vecteur en utilisant seq
:
(seq [])
;;=> nil
(seq [:foo])
;;=> (:foo)
(seq [:foo :bar])
;;=> (:foo :bar)
Comme les vecteurs sont indexés, vous pouvez également obtenir une séquence inversée des éléments d'un vecteur en utilisant rseq
:
(rseq [])
;;=> nil
(rseq [:foo])
;;=> (:foo)
(rseq [:foo :bar])
;;=> (:bar :foo)
Notez que, bien que toutes les listes soient des séquences et que les séquences soient affichées de la même manière que les listes, toutes les séquences ne sont pas des listes!
'(:foo :bar)
;;=> (:foo :bar)
(seq [:foo :bar])
;;=> (:foo :bar)
(list? '(:foo :bar))
;;=> true
(list? (seq [:foo :bar]))
;;=> false
(list? (rseq [:foo :bar]))
;;=> false
Ensembles
Comme les cartes, les ensembles sont associatifs et non ordonnés. Contrairement aux cartes, qui contiennent des correspondances entre les clés et les valeurs, elles définissent essentiellement la correspondance entre les clés et elles-mêmes.
Un ensemble est désigné par des accolades précédé d'un octothorpe:
#{}
;;=> #{}
#{:foo}
;;=> #{:foo}
#{:foo :bar}
;;=> #{:bar :foo}
Comme pour les cartes, l'ordre dans lequel les éléments apparaissent dans un ensemble littéral n'a pas d'importance:
(= #{:foo :bar} #{:bar :foo})
;;=> true
Vous pouvez tester si quelque chose est un ensemble en utilisant l' set?
prédicat:
(set? #{})
;;=> true
(set? #{:foo})
;;=> true
(set? #{:foo :bar})
;;=> true
(set? nil)
;;=> false
(set? 42)
;;=> false
(set? :foo)
;;=> false
Vous pouvez tester si une carte contient un élément donné dans le temps "constant" en utilisant le contains?
prédicat:
(contains? #{} :foo)
;;=> false
(contains? #{:foo} :foo)
;;=> true
(contains? #{:foo} :bar)
;;=> false
(contains? #{} nil)
;;=> false
(contains? #{nil} nil)
;;=> true
De plus, les ensembles eux-mêmes sont des fonctions qui prennent un élément et renvoient cet élément s'il est présent dans l'ensemble, ou nil
s'il ne l'est pas:
(#{} :foo)
;;=> nil
(#{:foo} :foo)
;;=> :foo
(#{:foo} :bar)
;;=> nil
(#{} nil)
;;=> nil
(#{nil} nil)
;;=> nil
Vous pouvez utiliser conj
pour obtenir un ensemble contenant tous les éléments d'un ensemble existant, plus un élément supplémentaire:
(conj #{} :foo)
;;=> #{:foo}
(conj (conj #{} :foo) :bar)
;;=> #{:bar :foo}
(conj #{:foo} :foo)
;;=> #{:foo}
Vous pouvez utiliser disj
pour obtenir un ensemble disj
tous les éléments d'un ensemble existant, moins un élément:
(disj #{} :foo)
;;=> #{}
(disj #{:foo} :foo)
;;=> #{}
(disj #{:foo} :bar)
;;=> #{:foo}
(disj #{:foo :bar} :foo)
;;=> #{:bar}
(disj #{:foo :bar} :bar)
;;=> #{:foo}
count
renvoie le nombre d'éléments, en temps constant:
(count #{})
;;=> 0
(count (conj #{} :foo))
;;=> 1
(count #{:foo :bar})
;;=> 2
Vous pouvez obtenir une séquence de tous les éléments d'un ensemble en utilisant seq
:
(seq #{})
;;=> nil
(seq #{:foo})
;;=> (:foo)
(seq #{:foo :bar})
;;=> (:bar :foo)
Plans
Contrairement à la liste, qui est une structure de données séquentielle, et le vecteur, qui est à la fois séquentiel et associatif, la carte est exclusivement une structure de données associative. Une carte consiste en un ensemble de correspondances entre les clés et les valeurs. Toutes les clés sont uniques, donc les cartes prennent en charge la recherche "constante" entre les clés et les valeurs.
Une carte est indiquée par des accolades:
{}
;;=> {}
{:foo :bar}
;;=> {:foo :bar}
{:foo :bar :baz :qux}
;;=> {:foo :bar, :baz :qux}
Chaque paire de deux éléments est une paire clé-valeur. Ainsi, par exemple, la première carte ci-dessus n'a pas de correspondance. Le second a un mapping, de la clé :foo
à la valeur :bar
. Le troisième a deux mappages, un de la clé :foo
à la valeur :bar
, et un de la clé :baz
à la valeur :qux
. Les cartes sont intrinsèquement non ordonnées, donc l'ordre dans lequel les correspondances apparaissent n'a pas d'importance:
(= {:foo :bar :baz :qux}
{:baz :qux :foo :bar})
;;=> true
Vous pouvez tester si quelque chose est une carte en utilisant la map?
prédicat:
(map? {})
;;=> true
(map? {:foo :bar})
;;=> true
(map? {:foo :bar :baz :qux})
;;=> true
(map? nil)
;;=> false
(map? 42)
;;=> false
(map? :foo)
;;=> false
Vous pouvez tester si une carte contient une clé donnée dans le temps "constant" en utilisant le contains?
prédicat:
(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
Vous pouvez obtenir la valeur associée à une clé en utilisant 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
De plus, les cartes elles-mêmes sont des fonctions qui prennent une clé et renvoient la valeur associée à cette clé:
({: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
Vous pouvez obtenir une entrée de carte complète (clé et valeur ensemble) en tant que vecteur à deux éléments en utilisant 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
Vous pouvez extraire la clé ou la valeur d'une entrée de carte en utilisant la key
ou val
respectivement:
(key (find {:foo :bar} :foo))
;;=> :foo
(val (find {:foo :bar} :foo))
;;=> :bar
Notez que, bien que toutes les entrées de carte Clojure soient des vecteurs, tous les vecteurs ne sont pas des entrées de carte. Si vous essayez d'appeler key
ou val
sur quelque chose qui n'est pas une entrée de carte, vous obtiendrez une ClassCastException
:
(key [:foo :bar])
;; java.lang.ClassCastException:
(val [:foo :bar])
;; java.lang.ClassCastException:
Vous pouvez tester si quelque chose est une entrée de carte en utilisant l' map-entry?
prédicat:
(map-entry? (find {:foo :bar} :foo))
;;=> true
(map-entry? [:foo :bar])
;;=> false
Vous pouvez utiliser assoc
pour obtenir une carte ayant toutes les mêmes paires clé-valeur qu'une carte existante, avec un mappage ajouté ou modifié:
(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}
Vous pouvez utiliser dissoc
pour obtenir une carte ayant toutes les mêmes paires clé-valeur qu'une carte existante, avec éventuellement un mappage supprimé:
(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
renvoie le nombre de mappages, en temps constant:
(count {})
;;=> 0
(count (assoc {} :foo :bar))
;;=> 1
(count {:foo :bar :baz :qux})
;;=> 2
Vous pouvez obtenir une séquence de toutes les entrées dans une carte en utilisant seq
:
(seq {})
;;=> nil
(seq {:foo :bar})
;;=> ([:foo :bar])
(seq {:foo :bar :baz :qux})
;;=> ([:foo :bar] [:baz :qux])
Encore une fois, les cartes ne sont pas ordonnées, de sorte que l'ordre des éléments dans une séquence obtenue en appelant seq
sur une carte n'est pas défini.
Vous pouvez obtenir une séquence de seulement les clés ou simplement les valeurs dans une carte en utilisant respectivement des keys
ou des 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 ajoute une syntaxe littérale pour représenter de manière plus concise une carte où les clés partagent le même espace de noms. Notez que la carte dans les deux cas est identique (la carte ne "connaît" pas l'espace de nommage par défaut), ceci est simplement une commodité syntaxique.
;; 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]"})