Los transductores son recetas de qué hacer con una secuencia de datos sin saber cuál es la secuencia subyacente (cómo hacerlo). Puede ser cualquier canal seq, asincrónico o tal vez observable.
Son componibles y polimórficos.
El beneficio es que no tiene que implementar todos los combinadores estándar cada vez que se agrega una nueva fuente de datos. Una y otra vez. Como efecto resultante, usted, como usuario, puede reutilizar esas recetas en diferentes fuentes de datos.
Actualización de anuncios
Antes de la versión 1.7 de Clojure, tenía tres formas de escribir consultas de flujo de datos:
- llamadas anidadas
(reduce + (filter odd? (map #(+ 2 %) (range 0 10))))
- composición funcional
(def xform
(comp
(partial filter odd?)
(partial map #(+ 2 %))))
(reduce + (xform (range 0 10)))
- macro de enhebrado
(defn xform [xs]
(->> xs
(map #(+ 2 %))
(filter odd?)))
(reduce + (xform (range 0 10)))
Con los transductores lo escribirás así:
(def xform
(comp
(map #(+ 2 %))
(filter odd?)))
(transduce xform + (range 0 10))
Todos hacen lo mismo. La diferencia es que nunca llamas a los transductores directamente, los pasas a otra función. Los transductores saben qué hacer, la función que obtiene el transductor sabe cómo. El orden de los combinadores es como si lo escribiera con macro de subprocesos (orden natural). Ahora puedes reutilizar xform
con el canal:
(chan 1 xform)
Los transductores mejoran la eficiencia y le permiten escribir código eficiente de una manera más modular.
Este es un recorrido decente .
En comparación con la composición de las llamadas a la antigua
map
,filter
,reduce
etc. se obtiene un mejor rendimiento debido a que no es necesario para construir colecciones intermedias entre cada paso, y en repetidas ocasiones caminar esas colecciones.En comparación con
reducers
, o componiendo manualmente todas sus operaciones en una sola expresión, es más fácil usar abstracciones, mejor modularidad y reutilización de funciones de procesamiento.fuente
map
/reduce
usar colecciones intermedias porque todos ellos construyen una cadena de iteradores. ¿Dónde me equivoco aquí?map
yfilter
crea colecciones intermedias cuando están anidadas.Los transductores son un medio de combinación para reducir funciones.
Ejemplo: las funciones reductoras son funciones que toman dos argumentos: un resultado hasta ahora y una entrada. Devuelven un nuevo resultado (hasta ahora). Por ejemplo
+
: con dos argumentos, puede pensar en el primero como el resultado hasta ahora y en el segundo como la entrada.Un transductor ahora podría tomar la función + y convertirla en una función doble más (duplica cada entrada antes de agregarla). Así es como se vería ese transductor (en términos más básicos):
Para la ilustración, sustituya
rfn
con+
para ver cómo+
se transforma en dos veces más:Entonces
ahora daría 12.
Las funciones reductoras devueltas por los transductores son independientes de cómo se acumula el resultado porque se acumulan con la función reductora que se les pasa, sin saber cómo. Aquí usamos en
conj
lugar de+
.Conj
toma una colección y un valor y devuelve una nueva colección con ese valor agregado.produciría [2 4 6]
También son independientes del tipo de fuente de entrada.
Se pueden encadenar varios transductores como una receta (encadenable) para transformar las funciones de reducción.
Actualización: dado que ahora hay una página oficial al respecto, recomiendo leerla: http://clojure.org/transducers
fuente
double
ytransduce
?Supongamos que desea utilizar una serie de funciones para transformar un flujo de datos. El shell de Unix le permite hacer este tipo de cosas con el operador de tubería, por ejemplo
(El comando anterior cuenta el número de usuarios con la letra r en mayúscula o minúscula en su nombre de usuario). Esto se implementa como un conjunto de procesos, cada uno de los cuales lee de la salida de los procesos anteriores, por lo que hay cuatro flujos intermedios. Puede imaginar una implementación diferente que componga los cinco comandos en un solo comando agregado, que leería su entrada y escribiría su salida exactamente una vez. Si las corrientes intermedias fueran caras y la composición barata, eso podría ser una buena compensación.
Lo mismo ocurre con Clojure. Hay varias formas de expresar una canalización de transformaciones, pero dependiendo de cómo lo haga, puede terminar con flujos intermedios que pasan de una función a la siguiente. Si tiene muchos datos, es más rápido componer esas funciones en una sola función. Los transductores facilitan la tarea. Una innovación anterior de Clojure, los reductores, también le permiten hacer eso, pero con algunas restricciones. Los transductores eliminan algunas de esas restricciones.
Entonces, para responder a su pregunta, los transductores no necesariamente harán que su código sea más corto o más comprensible, pero su código probablemente tampoco será más largo o menos comprensible, y si está trabajando con muchos datos, los transductores pueden hacer su código Más rápido.
Esta es una descripción general bastante buena de los transductores.
fuente
pmap
, que no parece recibir suficiente atención. Si estámap
haciendo ping a una función costosa sobre una secuencia, hacer que la operación sea paralela es tan fácil como agregar "p". No es necesario cambiar nada más en su código, y está disponible ahora, no alfa, no beta. (Si la función crea secuencias intermedias, entonces los transductores podrían ser más rápidos, supongo.)Rich Hickey dio una charla sobre 'Transducers' en la conferencia Strange Loop 2014 (45 min).
Explica de manera sencilla qué son los transductores, con ejemplos del mundo real: procesamiento de maletas en un aeropuerto. Separa claramente los diferentes aspectos y los contrasta con los enfoques actuales. Hacia el final, da la justificación de su existencia.
Video: https://www.youtube.com/watch?v=6mTbuzafcII
fuente
Descubrí que leer ejemplos de transducers-js me ayuda a entenderlos en términos concretos de cómo podría usarlos en el código del día a día.
Por ejemplo, considere este ejemplo (tomado de README en el enlace anterior):
Por un lado, el uso se
xf
ve mucho más limpio que la alternativa habitual con Underscore.fuente
t.into([], t.comp(t.map(inc), t.filter(isEven)), [0,1,2,3,4])
Los transductores son (¡a mi entender!) Funciones que toman una función reductora y devuelven otra. Una función reductora es aquella que
Por ejemplo:
En este caso, mi transductor toma una función de filtrado de entrada que aplica a 0, entonces, ¿si ese valor es par? en el primer caso, el filtro pasa ese valor al contador, luego filtra el siguiente valor. En lugar de filtrar primero y luego pasar todos esos valores para contar.
Es lo mismo en el segundo ejemplo, verifica un valor a la vez y si ese valor es menor que 3, entonces permite contar sumar 1.
fuente
Una clara definición de transductor está aquí:
Para entenderlo, consideremos el siguiente ejemplo simple:
¿Qué tal si queremos saber cuántos niños hay en el pueblo? Lo podemos averiguar fácilmente con el siguiente reductor:
Aquí hay otra forma de hacerlo:
Además, también es muy poderoso cuando se tienen en cuenta subgrupos. Por ejemplo, si quisiéramos saber cuántos niños hay en Brown Family, podemos ejecutar:
Espero que estos ejemplos le resulten útiles. Puedes encontrar más aquí
Espero eso ayude.
Clemencio Morales Lucas.
fuente
Escribí en un blog sobre esto con un ejemplo de clojurescript que explica cómo las funciones de secuencia ahora son extensibles al poder reemplazar la función de reducción.
Este es el punto de los transductores tal como lo leo. Si piensa en la operación
cons
oconj
que está codificada en operaciones comomap
,filter
etc., la función de reducción era inalcanzable.Con los transductores, la función de reducción está desacoplada y puedo reemplazarla como lo hice con la matriz javascript nativa
push
gracias a los transductores.filter
y amigos tienen una nueva operación de 1 aridad que devolverá una función de transducción que puede usar para proporcionar su propia función de reducción.fuente
Aquí está mi (en su mayoría) jerga y respuesta sin código.
Piense en los datos de dos maneras, una secuencia (valores que ocurren a lo largo del tiempo, como eventos) o una estructura (datos que existen en un momento determinado, como una lista, un vector, una matriz, etc.).
Hay determinadas operaciones que puede que desee realizar sobre corrientes o estructuras. Una de esas operaciones es el mapeo. Una función de mapeo podría incrementar cada elemento de datos (asumiendo que es un número) en 1 y es de esperar que pueda imaginar cómo esto podría aplicarse a una secuencia o estructura.
Una función de mapeo es sólo una de una clase de funciones que a veces se denominan "funciones reductoras". Otra función de reducción común es el filtro que elimina los valores que coinciden con un predicado (por ejemplo, elimina todos los valores que son pares).
Los transductores le permiten "envolver" una secuencia de una o más funciones reductoras y producir un "paquete" (que en sí mismo es una función) que funciona en ambos flujos o estructuras. Por ejemplo, podría "empaquetar" una secuencia de funciones reductoras (por ejemplo, filtrar números pares, luego asignar los números resultantes para incrementarlos en 1) y luego usar ese "paquete" de transductor en un flujo o estructura de valores (o ambos) .
Entonces, ¿qué tiene de especial esto? Por lo general, las funciones de reducción no se pueden componer de manera eficiente para trabajar tanto en flujos como en estructuras.
Entonces, el beneficio para usted es que puede aprovechar su conocimiento sobre estas funciones y aplicarlas a más casos de uso. El costo para usted es que tiene que aprender algo de maquinaria adicional (es decir, el transductor) para darle esta potencia adicional.
fuente
Por lo que tengo entendido, son como bloques de construcción , desacoplados de la implementación de entrada y salida. Solo define la operación.
Como la implementación de la operación no está en el código de la entrada y no se hace nada con la salida, los transductores son extremadamente reutilizables. Me recuerdan a Flow s en Akka Streams .
También soy nuevo en los transductores, lo siento por la respuesta posiblemente poco clara.
fuente
Encuentro que esta publicación le brinda una vista más panorámica del transductor.
https://medium.com/@roman01la/understanding-transducers-in-javascript-3500d3bd9624
fuente