Suche…


Einführung

Transducer sind komponierbare Komponenten zur Verarbeitung von Daten unabhängig vom Kontext. Damit können sie Sammlungen, Streams, Kanäle usw. ohne Kenntnis ihrer Eingabequellen oder Ausgabesenken verarbeiten.

Die Clojure-Kernbibliothek wurde in 1.7 erweitert, sodass die Sequenzfunktionen wie map, filter, take usw. einen Transducer zurückgeben, wenn er ohne Sequenz aufgerufen wird. Da Transducer Funktionen mit bestimmten Kontrakten sind, können sie mit der normalen comp Funktion zusammengestellt werden.

Bemerkungen

Wandler ermöglichen die Kontrolle der Faulheit während des Verbrauchs. Zum Beispiel into ist bestrebt , wie zu erwarten, aber sequence wird die Sequenz durch den Wandler lazily verbrauchen. Die Faulheitsgarantie ist jedoch anders. Es wird genug von der Quelle verbraucht, um anfangs ein Element zu erzeugen:

(take 0 (sequence (map #(do (prn '-> %) %)) (range 5)))
;; -> 0
;; => ()

Oder entscheiden Sie, ob die Liste leer ist:

(take 0 (sequence (comp (map #(do (prn '-> %) %)) (remove number?)) (range 5)))
;; -> 0
;; -> 1
;; -> 2
;; -> 3
;; -> 4
;; => ()

Was unterscheidet sich vom üblichen Lazy-Sequence-Verhalten:

(take 0 (map #(do (prn '-> %) %) (range 5)))
;; => ()

Kleiner Wandler, der auf einen Vektor angewendet wird

(let [xf (comp
           (map inc)
           (filter even?))]
  (transduce xf + [1 2 3 4 5 6 7 8 9 10]))
;; => 30

In diesem Beispiel wird ein Transducer erstellt, der dem lokalen xf zugewiesen ist, und er wird mithilfe von transduce auf einige Daten xf . Der Transducer fügt jedem seiner Eingänge einen hinzu und gibt nur die geraden Zahlen zurück.

transduce ist wie " reduce und reduce die Eingabeauflistung mithilfe der + -Funktion auf einen einzelnen Wert.

Dies liest sich wie das letzte Thread-Makro, trennt jedoch die Eingabedaten von den Berechnungen.

(->> [1 2 3 4 5 6 7 8 9 10]
     (map inc)
     (filter even?)
     (reduce +))
;; => 30

Aufnehmer aufbringen

(def xf (filter keyword?))

Bewerben Sie sich auf eine Sammlung und geben Sie eine Sequenz zurück:

(sequence xf [:a 1 2 :b :c]) ;; => (:a :b :c)

Auf eine Sammlung anwenden, um die resultierende Sammlung mit einer anderen Funktion zu reduzieren:

(transduce xf str [:a 1 2 :b :c]) ;; => ":a:b:c"

Auf eine Sammlung anwenden und das Ergebnis in eine andere Sammlung conj :

(into [] xf [:a 1 2 :b :c]) ;; => [:a :b :c]

Erstellen Sie einen asynchronen Core-Kanal, der Nachrichten mit einem Transducer filtert:

(require '[clojure.core.async :refer [chan >!! <!! poll!]])
(doseq [e [:a 1 2 :b :c]] (>!! ch e))
(<!! ch) ;; => :a
(<!! ch) ;; => :b
(<!! ch) ;; => :c
(poll! ch) ;;=> nil

Transducer erstellen / verwenden

Die am häufigsten verwendeten Funktionen in Clojure-Map und -Filtern wurden geändert, um Transducer zurückzugeben (composable algorithmic transformations), sofern sie nicht mit einer Collection aufgerufen werden. Das bedeutet:

(map inc) gibt einen Transducer zurück und tut dies auch (filter odd?)

Der Vorteil: Die Funktionen können von comp zu einer einzigen Funktion zusammengestellt werden, dh die Sammlung muss nur einmal durchlaufen werden. Spart in einigen Szenarien die Laufzeit um über 50%.

Definition:

(def composed-fn (comp (map inc) (filter odd?)))

Verwendungszweck:

;; So instead of doing this:
(->> [1 8 3 10 5]
     (map inc)
    (filter odd?))
;; Output [9 11]

;; We do this: 
(into [] composed-fn [1 8 3 10 5])
;; Output: [9 11]


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow