clojure
Restrukturyzacja Clojure
Szukaj…
Niszczenie wektora
Oto jak możesz zniszczyć wektor:
(def my-vec [1 2 3])
Następnie, na przykład w bloku let
, możesz bardzo zwięźle wyodrębnić wartości z wektora w następujący sposób:
(let [[x y] my-vec]
(println "first element:" x ", second element: " y))
;; first element: 1 , second element: 2
Niszczenie mapy
Oto jak możesz zniszczyć mapę:
(def my-map {:a 1 :b 2 :c 3})
Następnie, na przykład, w bloku let możesz bardzo zwięźle wyodrębnić wartości z mapy w następujący sposób:
(let [{x :a y :c} my-map]
(println ":a val:" x ", :c val: " y))
;; :a val: 1 , :c val: 3
Zauważ, że wartości wyodrębniane w każdym odwzorowaniu znajdują się po lewej stronie, a klawisze, z którymi są powiązane, znajdują się po prawej stronie.
Jeśli chcesz zniszczyć wartości powiązań o takich samych nazwach jak klucze, możesz użyć tego skrótu:
(let [{:keys [a c]} my-map]
(println ":a val:" a ", :c val: " c))
;; :a val: 1 , :c val: 3
Jeśli twoje klucze są łańcuchami, możesz użyć prawie takiej samej struktury:
(let [{:strs [foo bar]} {"foo" 1 "bar" 2}]
(println "FOO:" foo "BAR: " bar ))
;; FOO: 1 BAR: 2
Podobnie w przypadku symboli:
(let [{:syms [foo bar]} {'foo 1 'bar 2}]
(println "FOO:" foo "BAR:" bar))
;; FOO: 1 BAR: 2
Jeśli chcesz zniszczyć zagnieżdżoną mapę, możesz zagnieździć formularze wiążące wyjaśnione powyżej:
(def data
{:foo {:a 1
:b 2}
:bar {:a 10
:b 20}})
(let [{{:keys [a b]} :foo
{a2 :a b2 :b} :bar} data]
[a b a2 b2])
;; => [1 2 10 20]
Przekształcanie pozostałych elementów w sekwencję
Powiedzmy, że masz taki wektor:
(def my-vec [1 2 3 4 5 6])
I chcesz wyodrębnić pierwsze 3 elementy i uzyskać pozostałe elementy w sekwencji. Można to zrobić w następujący sposób:
(let [[x y z & remaining] my-vec]
(println "first:" x ", second:" y "third:" z "rest:" remaining))
;= first: 1 , second: 2 third: 3 rest: (4 5 6)
Restrukturyzacja wektorów zagnieżdżonych
Możesz zniszczyć zagnieżdżone wektory:
(def my-vec [[1 2] [3 4]])
(let [[[a b][c d]] my-vec]
(println a b c d))
;; 1 2 3 4
Niszczenie mapy z wartościami domyślnymi
Czasami chcesz zniszczyć klucz pod mapą, która może nie być obecna na mapie, ale potrzebujesz domyślnej wartości zniszczonej wartości. Możesz to zrobić w ten sposób:
(def my-map {:a 3 :b 4}) (let [{a :a b :b :keys [c d] :or {a 1 c 2}} my-map] (println a b c d)) ;= 3 4 2 nil
Destrukturyzacja parametrów fn
Destructurling działa w wielu miejscach, a także na liście parametrów fn:
(defn my-func [[_ a b]] (+ a b)) (my-func [1 2 3]) ;= 5 (my-func (range 5)) ;= 3
Destrukturyzacja działa również w przypadku konstrukcji & rest
z listy parametrów:
(defn my-func2 [& [_ a b]] (+ a b)) (my-func2 1 2 3) ;= 5 (apply my-func2 (range 5)) ;= 3
Konwertowanie reszty sekwencji na mapę
Destrukturyzacja daje również możliwość interpretacji sekwencji jako mapy:
(def my-vec [:a 1 :b 2])
(def my-lst '("smthg else" :c 3 :d 4))
(let [[& {:keys [a b]}] my-vec
[s & {:keys [c d]} my-lst]
(+ a b c d)) ;= 10
Jest to przydatne do definiowania funkcji o nazwanych parametrach :
(defn my-func [a b & {:keys [c d] :or {c 3 d 4}}]
(println a b c d))
(my-func 1 2) ;= 1 2 3 4
(my-func 3 4 :c 5 :d 6) ;= 3 4 5 6
Przegląd
Destrukturyzacja pozwala wyodrębnić dane z różnych obiektów do odrębnych zmiennych. W każdym z poniższych przykładów każda zmienna jest przypisana do własnego łańcucha ( a
= "a"
, b = "b"
i c.)
Rodzaj | Przykład | Wartość data / komentarza |
---|---|---|
vec | (let [[abc] data ...) | ["a" "b" "c"] |
zagnieżdżone vec | (let [[[ab] [cd]] data ...) | [["a" "b"] ["c" "d"]] |
map | (let [{a :ab :bc :c} data ...) | {:a "a" :b "b" :c "c"} |
- alternatywa: | (let [{:keys [abc]} data ...) | Kiedy zmienne są nazywane po kluczach. |
Wskazówki:
- Wartości domyślne można podać za pomocą
:or
, w przeciwnym razie wartość domyślna tonil
- Użyj
& rest
aby zapisaćseq
dowolnych dodatkowych wartości wrest
, w przeciwnym razie dodatkowe wartości zostaną zignorowane - Powszechnym i użytecznym zastosowaniem destrukcji są parametry funkcji
- Możesz przypisać niechciane części do zmiennej wyrzucanej (konwencjonalnie:
_
)
Niszczenie i wiązanie z nazwą klucza
Czasami podczas mapowania destrukcji chciałbyś powiązać zniszczone wartości z ich odpowiednimi nazwami kluczy. W zależności od ziarnistości struktury danych użycie standardowego schematu destrukcji może być nieco szczegółowe .
Powiedzmy, że mamy zapis oparty na mapie:
(def john {:lastname "McCarthy" :firstname "John" :country "USA"})
normalnie byśmy to zniszczyli w ten sposób:
(let [{lastname :lastname firstname :firstname country :country} john]
(str firstname " " lastname ", " country))
;;"John McCarthy, USA"
tutaj struktura danych jest dość prosta i ma tylko 3 miejsca ( imię, nazwisko, kraj ), ale wyobraź sobie, jak uciążliwe byłoby, gdybyśmy musieli powtórzyć wszystkie nazwy kluczy dwa razy, aby uzyskać bardziej szczegółową strukturę danych (mając znacznie więcej miejsc niż tylko 3) .
Zamiast tego lepszym sposobem radzenia sobie z tym jest użycie :keys
(ponieważ nasze klucze są tutaj słowami kluczowymi ) i wybranie nazwy klucza, z którym chcielibyśmy się powiązać:
(let [{:keys [firstname lastname country]} john]
(str firstname " " lastname ", " country))
;;"John McCarthy, USA"
Ta sama intuicyjna logika dotyczy innych typów kluczy, takich jak symbole (using :syms
) i zwykłe stare ciągi znaków (using :strs
)
;; using strings as keys
(def john {"lastname" "McCarthy" "firstname" "John" "country" "USA"})
;;#'user/john
;; destructuring string-keyed map
(let [{:strs [lastname firstname country]} john]
(str firstname " " lastname ", " country))
;;"John McCarthy, USA"
;; using symbols as keys
(def john {'lastname "McCarthy" 'firstname "John" 'country "USA"})
;; destructuring symbol-keyed map
(let [{:syms [lastname firstname country]} john]
(str firstname " " lastname ", " country))
;;"John McCarthy, USA"
Restrukturyzacja i nadanie nazwy pierwotnej wartości argumentu
(defn print-some-items
[[a b :as xs]]
(println a)
(println b)
(println xs))
(print-some-items [2 3])
Ten przykład drukuje dane wyjściowe
2
3
[2 3]
Argument jest zniszczony, a pozycje 2
i 3
są przypisane do symboli a
i b
. Oryginalny argument, cały wektor [2 3]
, jest również przypisany do symbolu xs
.