Buscar..


Introducción

Los transductores son componentes componibles para procesar datos independientemente del contexto. Por lo tanto, se pueden utilizar para procesar colecciones, flujos, canales, etc. sin conocimiento de sus fuentes de entrada o receptores de salida.

La biblioteca central de Clojure se amplió en 1.7 para que la secuencia funcione como mapa, filtro, toma, etc. devuelva un transductor cuando se le llame sin una secuencia. Debido a que los transductores son funciones con contratos específicos, se pueden componer utilizando la función de comp normal.

Observaciones

Los transductores permiten controlar la pereza a medida que se consumen. Por ejemplo into está ansioso como sería de esperar, pero sequence perezosamente consumirá la secuencia a través del transductor. Sin embargo, la garantía de pereza es diferente. Se consumirá suficiente de la fuente para producir un elemento inicialmente:

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

O decide si la lista está vacía:

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

Que difiere del comportamiento habitual de la secuencia perezosa:

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

Pequeño transductor aplicado a un vector.

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

Este ejemplo crea un transductor asignado a la xf local y utiliza transduce para aplicarlo a algunos datos. El transductor agrega uno a cada una de sus entradas y solo devuelve los números pares.

transduce es como reduce , y colapsa la colección de entrada a un solo valor usando la función + provista.

Esto se lee como la macro del último hilo, pero separa los datos de entrada de los cálculos.

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

Aplicando transductores

(def xf (filter keyword?))

Aplicar a una colección, devolviendo una secuencia:

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

Aplicar a una colección, reduciendo la colección resultante con otra función:

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

Aplicar a una colección y conj el resultado en otra colección:

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

Cree un canal asíncrono central que use un transductor para filtrar mensajes:

(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

Creando / Usando Transductores

Por lo tanto, las funciones más utilizadas en el mapa y el filtro de Clojure se han modificado para devolver los transductores (transformaciones algorítmicas compuestas), si no se llaman con una colección. Eso significa:

(map inc) devuelve un transductor y también lo hace (filter odd?)

La ventaja: las funciones se pueden componer en una sola función por comp, lo que significa atravesar la colección solo una vez. Ahorra tiempo de ejecución en más del 50% en algunos escenarios.

Definición:

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

Uso:

;; 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
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow