Zoeken…


Invoering

Transducers zijn configureerbare componenten voor het verwerken van gegevens onafhankelijk van de context. Ze kunnen dus worden gebruikt om collecties, streams, kanalen, enz. Te verwerken zonder kennis van hun invoerbronnen of uitvoerputten.

De Clojure-kernbibliotheek werd uitgebreid in 1.7 zodat de reeks functioneert zoals map, filter, take, etc. retourneert een transducer wanneer deze zonder een reeks wordt aangeroepen. Omdat transducers functies zijn met specifieke contracten, kunnen ze worden samengesteld met behulp van de normale comp functie.

Opmerkingen

Met transducers kan de luiheid onder controle worden gehouden wanneer ze worden geconsumeerd. Bijvoorbeeld into wil graag zoals verwacht, maar sequence zal lui verbruiken de volgorde door de omzetter. De garantie voor luiheid is echter anders. Genoeg van de bron zal worden verbruikt om in eerste instantie een element te produceren:

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

Of beslis of de lijst leeg is:

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

Dat verschilt van het gebruikelijke luie volgordegedrag:

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

Kleine transducer toegepast op een vector

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

In dit voorbeeld wordt een transducer gemaakt die is toegewezen aan de lokale xf en wordt transduce gebruikt om deze op sommige gegevens toe te passen. De transducer voegt één toe aan elk van zijn ingangen en retourneert alleen de even getallen.

transduce is als reduce , en vouwt de invoerverzameling samen tot een enkele waarde met behulp van de meegeleverde + -functie.

Dit leest als de thread-last macro, maar scheidt de invoergegevens van de berekeningen.

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

Transducers toepassen

(def xf (filter keyword?))

Toepassen op een verzameling en een reeks retourneren:

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

Toepassen op een verzameling, waarbij de resulterende verzameling wordt verminderd met een andere functie:

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

Toepassen op een verzameling en conj het resultaat in een andere verzameling:

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

Maak een asynchrone kernkanaal dat een transducer gebruikt om berichten te filteren:

(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

Transducers maken / gebruiken

Dus de meest gebruikte functies op Clojure-kaart en -filter zijn aangepast om transducers (configureerbare algoritmische transformaties) te retourneren, zo niet opgeroepen met een verzameling. Dat betekent:

(map inc) retourneert een transducer en dat doet (filter odd?)

Het voordeel: de functies kunnen worden samengevoegd tot een enkele functie door comp, wat betekent dat u de verzameling slechts eenmaal doorloopt. Bespaart runtime met meer dan 50% in sommige scenario's.

Definitie:

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

Gebruik:

;; 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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow