Recherche…


Introduction

Les transducteurs sont des composants composables permettant de traiter des données indépendamment du contexte. Ils peuvent donc être utilisés pour traiter des collections, des flux, des canaux, etc. sans connaître leurs sources d'entrée ou leurs puits de sortie.

La bibliothèque principale de Clojure a été étendue en 1.7 pour que les fonctions de séquence telles que carte, filtre, prise, etc. renvoient un transducteur lorsqu'il est appelé sans séquence. Parce que les transducteurs sont des fonctions avec des contrats spécifiques, ils peuvent être composés en utilisant la normale comp fonction.

Remarques

Les transducteurs permettent de contrôler la paresse au fur et à mesure de leur consommation. Par exemple, into est comme on peut s'y attendre, mais la sequence consommera paresseusement la séquence à travers le transducteur. Cependant, la garantie de paresse est différente. Assez de la source sera consommée pour produire un élément initialement:

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

Ou décidez si la liste est vide:

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

Ce qui diffère du comportement habituel de la séquence paresseuse:

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

Petit transducteur appliqué à un vecteur

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

Cet exemple crée un transducteur affecté au xf local et utilise la transduce pour l'appliquer à certaines données. Le transducteur en ajoute un à chacune de ses entrées et ne renvoie que les nombres pairs.

transduce est comme reduce et réduit la collection d'entrée à une valeur unique en utilisant la fonction + fournie.

Cela se lit comme la dernière macro thread, mais sépare les données d'entrée des calculs.

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

Application de transducteurs

(def xf (filter keyword?))

Appliquer à une collection en renvoyant une séquence:

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

Appliquer à une collection en réduisant la collection résultante avec une autre fonction:

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

Appliquer à une collection et conj le résultat à une autre collection:

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

Créez un canal asynchrone principal qui utilise un transducteur pour filtrer les messages:

(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

Création / utilisation de transducteurs

Ainsi, les fonctions les plus utilisées sur les cartes et les filtres de Clojure ont été modifiées pour renvoyer des transducteurs (transformations algorithmiques composables), sinon appelés avec une collection. Cela signifie:

(map inc) renvoie un transducteur et le fait aussi (filter odd?)

L'avantage: les fonctions peuvent être composées en une seule fonction par comp, ce qui signifie traverser la collection une seule fois. Enregistre le temps d'exécution de plus de 50% dans certains scénarios.

Définition:

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

Usage:

;; 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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow