Szukaj…


Składnia

  • '()()
  • '(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"} (wpisy są sortowane według klucza, gdy są używane jako sekwencja)
  • #{}#{}
  • #{1 2 3 4 5}#{4 3 2 5 1} (nieuporządkowany)
  • ( hash-set 1 2 3 4 5)#{2 5 4 1 3} (nieuporządkowany)
  • ( sorted-set 2 5 4 3 1)#{1 2 3 4 5}

Kolekcje

Wszystkie wbudowane kolekcje Clojure są niezmienne i heterogeniczne, mają dosłowną składnię i obsługują funkcje conj , count i seq .

  • conj zwraca nową kolekcję, która jest równoważna istniejącej kolekcji z elementem „dodanym”, w „stałym” lub logarytmicznym czasie. Co dokładnie to oznacza, zależy od kolekcji.
  • count zwraca liczbę elementów w kolekcji w stałym czasie.
  • seq zwraca nil dla pustej kolekcji lub sekwencję elementów dla niepustej kolekcji w stałym czasie.

Listy

Lista jest oznaczona nawiasami:

()
;;=> ()

Lista Clojure to lista pojedynczo połączona . conj „conjoins” nowy element do kolekcji w najbardziej efektywny lokalizacji. W przypadku list jest to na początku:

(conj () :foo)
;;=> (:foo)

(conj (conj () :bar) :foo)
;;=> (:foo :bar)

W przeciwieństwie do innych kolekcji niepuste listy są oceniane jako wywołania specjalnych formularzy, makr lub funkcji. Dlatego, chociaż (:foo) jest dosłowną reprezentacją listy zawierającej :foo jako jedyny element, ocena (:foo) w REPL spowoduje zgłoszenie IllegalArgumentException ponieważ słowa kluczowego nie można wywołać jako funkcji zerowej .

(:foo)
;; java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :foo

Aby uniemożliwić Clojure ocenę niepustej listy, możesz ją quote :

'(:foo)
;;=> (:foo)

'(:foo :bar)
;;=> (:foo :bar)

Niestety powoduje to, że elementy nie są oceniane:

(+ 1 1)
;;=> 2

'(1 (+ 1 1) 3)
;;=> (1 (+ 1 1) 3)

Z tego powodu zwykle będziesz chciał użyć list , funkcji variadic, która ocenia wszystkie argumenty i wykorzystuje te wyniki do utworzenia listy:

(list)
;;=> ()

(list :foo)
;;=> (:foo)

(list :foo :bar)
;;=> (:foo :bar)

(list 1 (+ 1 1) 3)
;;=> (1 2 3)

count zwraca liczbę elementów w stałym czasie:

(count ())
;;=> 0

(count (conj () :foo))
;;=> 1

(count '(:foo :bar))
;;=> 2

Możesz sprawdzić, czy coś jest listą za pomocą list? orzec:

(list? ())
;;=> true

(list? '(:foo :bar))
;;=> true

(list? nil)
;;=> false

(list? 42)
;;=> false

(list? :foo)
;;=> false

Pierwszy element listy możesz uzyskać za pomocą peek :

(peek ())
;;=> nil

(peek '(:foo))
;;=> :foo

(peek '(:foo :bar))
;;=> :foo

Możesz uzyskać nową listę bez pierwszego elementu za pomocą pop :

(pop '(:foo))
;;=> ()

(pop '(:foo :bar))
;;=> (:bar)

Pamiętaj, że jeśli spróbujesz pop pustą listę, otrzymasz IllegalStateException :

(pop ())
;; java.lang.IllegalStateException: Can't pop empty list

Wreszcie, wszystkie listy są sekwencjami, więc możesz zrobić wszystko z listą, którą możesz zrobić z dowolną inną sekwencją. Rzeczywiście, z wyjątkiem pustej listy, wywołanie seq na liście zwraca dokładnie ten sam obiekt:

(seq ())
;;=> nil

(seq '(:foo))
;;=> (:foo)

(seq '(:foo :bar))
;;=> (:foo :bar)

(let [x '(:foo :bar)]
  (identical? x (seq x)))
;;=> true

Sekwencje

Sekwencja jest bardzo podobna do listy: jest niezmiennym obiektem, który może dać ci swój first element lub rest jego elementów w stałym czasie. Można również cons truct nową sekwencję z istniejącej sekwencji i element trzymać na początku.

Możesz sprawdzić, czy coś jest sekwencją za pomocą seq? orzec:

(seq? nil)
;;=> false

(seq? 42)
;;=> false

(seq? :foo)
;;=> false

Jak już wiesz, listy są sekwencjami:

(seq? ())
;;=> true

(seq? '(:foo :bar))
;;=> true

Wszystko, co otrzymujesz przez wywołanie seq lub rseq lub keys lub vals w niepustym zbiorze, jest również sekwencją:

(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

Pamiętaj, że wszystkie listy są sekwencjami, ale nie wszystkie sekwencje są listami. Podczas gdy listy obsługują peek i pop i count w stałym czasie, generalnie sekwencja nie musi obsługiwać żadnej z tych funkcji. Jeśli spróbujesz wywołać peek lub pop w sekwencji, która nie obsługuje również interfejsu stosu Clojure, otrzymasz 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

Jeśli wywołasz count w sekwencji, która nie implementuje count w stałym czasie, nie pojawi się błąd; zamiast tego Clojure będzie przemierzał całą sekwencję aż do końca, a następnie zwróci liczbę elementów, które przemierzył. Oznacza to, że dla sekwencji ogólnych count jest liniowa, a nie stała, w czasie. Możesz sprawdzić, czy coś obsługuje count czasu stałego za pomocą counted? orzec:

(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

Jak wspomniano powyżej, możesz użyć first aby uzyskać pierwszy element sekwencji. Zauważ, że first zadzwoni seq ich argumentu, dzięki czemu może być używany na cokolwiek „seqable”, a nie tylko rzeczywistych sekwencji:

(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

Również jak wspomniano powyżej, możesz użyć rest aby uzyskać sekwencję zawierającą wszystkie oprócz pierwszego elementu istniejącej sekwencji. Podobnie jak first , wywołuje seq w swoim argumencie. Jednak nie wywołuje seq po swoim wyniku! Oznacza to, że jeśli wywołasz rest na sekwencji, która zawiera mniej niż dwa elementy, otrzymasz return () zamiast nil :

(rest nil)
;;=> ()

(rest '(:foo))
;;=> ()

(rest '(:foo :bar))
;;=> (:bar)

(rest [:foo])
;;=> ()

(rest [:foo :bar])
;;=> (:bar)

(rest {:foo :bar})
;;=> ()

(rest #{:foo})
;;=> ()

Jeśli chcesz odzyskać nil gdy nie ma już więcej elementów w sekwencji, możesz użyć next zamiast rest :

(next nil)
;;=> nil

(next '(:foo))
;;=> nil

(next [:foo])
;;=> nil

Możesz użyć funkcji cons aby utworzyć nową sekwencję, która zwróci pierwszy argument dla first i drugi argument dla rest :

(cons :foo nil)
;;=> (:foo)

(cons :foo (cons :bar nil))
;;=> (:foo :bar)

Clojure zapewnia dużą bibliotekę sekwencji z wieloma funkcjami do obsługi sekwencji. Ważną rzeczą w tej bibliotece jest to, że działa ona z wszystkim, co jest „seqable”, a nie tylko z listami. Dlatego koncepcja sekwencji jest tak przydatna; oznacza to, że pojedyncza funkcja, na przykład reduce , działa doskonale w każdej kolekcji:

(reduce + '(1 2 3))
;;=> 6

(reduce + [1 2 3])
;;=> 6

(reduce + #{1 2 3})
;;=> 6

Innym powodem, dla którego sekwencje są przydatne, jest to, że ponieważ nie nakazują żadnej konkretnej implementacji first i rest , pozwalają na leniwe sekwencje, których elementy są realizowane tylko w razie potrzeby.

Biorąc pod uwagę wyrażenie, które utworzyłoby sekwencję, możesz owinąć to wyrażenie w makro lazy-seq aby uzyskać obiekt, który działa jak sekwencja, ale faktycznie oceni to wyrażenie, gdy zostanie o to poproszony przez funkcję seq , w który punkt zbuforuje wynik wyrażenia, a następnie przekaże first i rest wywołań do wyniku w pamięci podręcznej.

W przypadku sekwencji skończonych sekwencja leniwa zwykle działa tak samo jak równoważna sekwencja chętna:

(seq [:foo :bar])
;;=> (:foo :bar)

(lazy-seq [:foo :bar])
;;=> (:foo :bar)

Jednak różnica staje się widoczna dla nieskończonych sekwencji:

(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)

Wektory

Wektor jest oznaczony nawiasami kwadratowymi:

[]
;;=> []

[:foo]
;;=> [:foo]

[:foo :bar]
;;=> [:foo :bar]

[1 (+ 1 1) 3]
;;=> [1 2 3]

Oprócz użycia dosłownej składni możesz także użyć funkcji vector do skonstruowania wektora:

(vector)
;;=> []

(vector :foo)
;;=> [:foo]

(vector :foo :bar)
;;=> [:foo :bar]

(vector 1 (+ 1 1) 3)
;;=> [1 2 3]

Możesz sprawdzić, czy coś jest wektorem za pomocą tego vector? orzec:

(vector? [])
;;=> true

(vector? [:foo :bar])
;;=> true

(vector? nil)
;;=> false

(vector? 42)
;;=> false

(vector? :foo)
;;=> false

conj dodaje elementy na końcu wektora:

(conj [] :foo)
;;=> [:foo]

(conj (conj [] :foo) :bar)
;;=> [:foo :bar]

(conj [] :foo :bar)
;;=> [:foo :bar]

count zwraca liczbę elementów w stałym czasie:

(count [])
;;=> 0

(count (conj [] :foo))
;;=> 1

(count [:foo :bar])
;;=> 2

Ostatni element wektora można uzyskać za pomocą peek :

(peek [])
;;=> nil

(peek [:foo])
;;=> :foo

(peek [:foo :bar])
;;=> :bar

Możesz uzyskać nowy wektor bez ostatniego elementu, używając pop :

(pop [:foo])
;;=> []

(pop [:foo :bar])
;;=> [:foo]

Pamiętaj, że jeśli spróbujesz rozbić pusty wektor, otrzymasz IllegalStateException :

(pop [])
;; java.lang.IllegalStateException: Can't pop empty vector

W przeciwieństwie do list, wektory są indeksowane. Możesz uzyskać element wektora przez indeks w „stałym” czasie, używając get :

(get [:foo :bar] 0)
;;=> :foo

(get [:foo :bar] 1)
;;=> :bar

(get [:foo :bar] -1)
;;=> nil

(get [:foo :bar] 2)
;;=> nil

Ponadto same wektory są funkcjami, które pobierają indeks i zwracają element pod tym indeksem:

([:foo :bar] 0)
;;=> :foo

([:foo :bar] 1)
;;=> :bar

Jednakże, jeśli można nazwać wektor z nieprawidłowym wskaźnikiem, dostaniesz IndexOutOfBoundsException zamiast nil :

([:foo :bar] -1)
;; java.lang.IndexOutOfBoundsException:

([:foo :bar] 2)
;; java.lang.IndexOutOfBoundsException:

Możesz uzyskać nowy wektor o innej wartości przy określonym indeksie, używając assoc :

(assoc [:foo :bar] 0 42)
;;=> [42 :bar]

(assoc [:foo :bar] 1 42)
;;=> [:foo 42]

Jeśli zdasz indeks równy count wektorów, Clojure doda element tak, jakbyś użył conj . Jeśli jednak przekażesz indeks, który jest ujemny lub większy niż count , otrzymasz 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:

Możesz uzyskać sekwencję elementów w wektorze za pomocą seq :

(seq [])
;;=> nil

(seq [:foo])
;;=> (:foo)

(seq [:foo :bar])
;;=> (:foo :bar)

Ponieważ wektory są indeksowane, można również uzyskać odwróconą sekwencję elementów wektora za pomocą rseq :

(rseq [])
;;=> nil

(rseq [:foo])
;;=> (:foo)

(rseq [:foo :bar])
;;=> (:bar :foo)

Zauważ, że chociaż wszystkie listy są sekwencjami, a sekwencje są wyświetlane w taki sam sposób jak listy, nie wszystkie sekwencje są listami!

'(:foo :bar)
;;=> (:foo :bar)

(seq [:foo :bar])
;;=> (:foo :bar)

(list? '(:foo :bar))
;;=> true

(list? (seq [:foo :bar]))
;;=> false

(list? (rseq [:foo :bar]))
;;=> false

Zestawy

Podobnie jak mapy, zestawy są asocjacyjne i nieuporządkowane. W przeciwieństwie do map, które zawierają mapowania od kluczy do wartości, zestawy zasadniczo mapują od kluczy do samych siebie.

Zestaw jest oznaczony nawiasami klamrowymi poprzedzonymi oktotorpą:

#{}
;;=> #{}

#{:foo}
;;=> #{:foo}

#{:foo :bar}
;;=> #{:bar :foo}

Podobnie jak w przypadku map, kolejność pojawiania się elementów w dosłownym zbiorze nie ma znaczenia:

(= #{:foo :bar} #{:bar :foo})
;;=> true

Możesz sprawdzić, czy coś jest zestawem, używając set? orzec:

(set? #{})
;;=> true

(set? #{:foo})
;;=> true

(set? #{:foo :bar})
;;=> true

(set? nil)
;;=> false

(set? 42)
;;=> false

(set? :foo)
;;=> false

Możesz przetestować, czy mapa zawiera dany przedmiot w „stałym” czasie, używając contains? orzec:

(contains? #{} :foo)
;;=> false

(contains? #{:foo} :foo)
;;=> true

(contains? #{:foo} :bar)
;;=> false

(contains? #{} nil)
;;=> false

(contains? #{nil} nil)
;;=> true

Ponadto same zestawy są funkcjami, które pobierają element i zwracają ten element, jeśli jest obecny w zestawie, lub nil jeśli nie jest:

(#{} :foo)
;;=> nil

(#{:foo} :foo)
;;=> :foo

(#{:foo} :bar)
;;=> nil

(#{} nil)
;;=> nil

(#{nil} nil)
;;=> nil

Możesz użyć conj aby uzyskać zestaw, który zawiera wszystkie elementy istniejącego zestawu oraz jeden dodatkowy element:

(conj #{} :foo)
;;=> #{:foo}

(conj (conj #{} :foo) :bar)
;;=> #{:bar :foo}

(conj #{:foo} :foo)
;;=> #{:foo}

Możesz użyć disj aby uzyskać zestaw, który zawiera wszystkie elementy istniejącego zestawu, minus jeden element:

(disj #{} :foo)
;;=> #{}

(disj #{:foo} :foo)
;;=> #{}

(disj #{:foo} :bar)
;;=> #{:foo}

(disj #{:foo :bar} :foo)
;;=> #{:bar}

(disj #{:foo :bar} :bar)
;;=> #{:foo}

count zwraca liczbę elementów w stałym czasie:

(count #{})
;;=> 0

(count (conj #{} :foo))
;;=> 1

(count #{:foo :bar})
;;=> 2

Możesz uzyskać sekwencję wszystkich elementów w zestawie za pomocą seq :

(seq #{})
;;=> nil

(seq #{:foo})
;;=> (:foo)

(seq #{:foo :bar})
;;=> (:bar :foo)

Mapy

W przeciwieństwie do listy, która jest sekwencyjną strukturą danych, oraz wektora, który jest zarówno sekwencyjny, jak i asocjacyjny, mapa jest wyłącznie asocjacyjną strukturą danych. Mapa składa się z zestawu odwzorowań od kluczy do wartości. Wszystkie klucze są unikalne, dlatego mapy obsługują „ciągłe” wyszukiwanie od kluczy do wartości.

Mapa jest oznaczona nawiasami klamrowymi:

{}
;;=> {}

{:foo :bar}
;;=> {:foo :bar}

{:foo :bar :baz :qux}
;;=> {:foo :bar, :baz :qux}

Każda para dwóch elementów jest parą klucz-wartość. Na przykład pierwsza mapa powyżej nie ma mapowań. Drugi ma jedno mapowanie, od klucza :foo do wartości :bar . Trzeci ma dwa odwzorowania, jeden od klucza :foo do wartości :bar , a drugi od klucza :baz do wartości :qux . Mapy są z natury nieuporządkowane, więc kolejność ich wyświetlania nie ma znaczenia:

(= {:foo :bar :baz :qux}
   {:baz :qux :foo :bar})
;;=> true

Możesz sprawdzić, czy coś jest mapą za pomocą map? orzec:

(map? {})
;;=> true

(map? {:foo :bar})
;;=> true

(map? {:foo :bar :baz :qux})
;;=> true

(map? nil)
;;=> false

(map? 42)
;;=> false

(map? :foo)
;;=> false

Możesz sprawdzić, czy mapa zawiera dany klucz w „stałym” czasie za pomocą contains? orzec:

(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

Możesz uzyskać wartość powiązaną z kluczem za pomocą 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

Ponadto same mapy są funkcjami, które pobierają klucz i zwracają wartość związaną z tym kluczem:

({: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

Możesz uzyskać cały wpis mapy (klucz i wartość razem) jako dwuelementowy wektor, używając 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

Możesz wyodrębnić klucz lub wartość z wpisu mapy, używając odpowiednio key lub val :

(key (find {:foo :bar} :foo))
;;=> :foo

(val (find {:foo :bar} :foo))
;;=> :bar

Zauważ, że chociaż wszystkie wpisy map Clojure są wektorami, nie wszystkie wektory są wpisami map. Jeśli spróbujesz wywołać key lub val na czymkolwiek, co nie jest wpisem na mapie, otrzymasz ClassCastException :

(key [:foo :bar])
;; java.lang.ClassCastException:

(val [:foo :bar])
;; java.lang.ClassCastException:

Możesz sprawdzić, czy coś jest wpisem na map-entry? używając wpisu map-entry? orzec:

(map-entry? (find {:foo :bar} :foo))
;;=> true

(map-entry? [:foo :bar])
;;=> false

Za pomocą narzędzia assoc można uzyskać mapę zawierającą wszystkie te same pary klucz-wartość, co istniejąca mapa, z dodanym lub zmienionym jednym mapowaniem:

(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}

Możesz użyć dissoc aby uzyskać mapę, która ma wszystkie te same pary klucz-wartość jak istniejąca mapa, z możliwym usunięciem jednego mapowania:

(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 zwraca liczbę mapowań w stałym czasie:

(count {})
;;=> 0

(count (assoc {} :foo :bar))
;;=> 1

(count {:foo :bar :baz :qux})
;;=> 2

Możesz uzyskać sekwencję wszystkich wpisów na mapie za pomocą seq :

(seq {})
;;=> nil

(seq {:foo :bar})
;;=> ([:foo :bar])

(seq {:foo :bar :baz :qux})
;;=> ([:foo :bar] [:baz :qux])

Ponownie, mapy są nieuporządkowane, więc kolejność elementów w sekwencji, które można uzyskać dzwoniąc seq na mapie jest niezdefiniowane.

Możesz uzyskać sekwencję samych kluczy lub tylko wartości na mapie, używając odpowiednio keys lub 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 dodaje dosłowną składnię, aby bardziej zwięźle przedstawić mapę, w której klucze mają tę samą przestrzeń nazw. Zauważ, że mapa w obu przypadkach jest identyczna (mapa nie „zna” domyślnej przestrzeni nazw), jest to jedynie wygoda składniowa.

;; 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]"})


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow