Transducer 개념 이해 (Clojure 언어)

17 Mar 2020 - Jake Na

Understanding transducer in clojure

Basics

(defn reduce [f result coll]
  (if (not= '() coll)
    (reduce f (f result (first coll)) (rest coll))
    result))

(reduce + 0 (range 10))
(defn reduce [f result coll]
  (if (not= '() coll)
    (reduce f (f result (first coll)) (rest coll))
    result))

(defn mapping [rf]
  (fn [result el]
    (rf result (inc el))))

(reduce (mapping conj) [] (range 10))

(defn filtering [rf]
  (fn [result el]
    (if (odd? el)
      (rf result el)
      result)))

(reduce (filtering conj) [] (range 10))
(defn mapping [f]
  (fn [rf]
    (fn [result el]
      (rf result (f el)))))

(reduce ((mapping inc) conj) [] (range 10))

(defn filtering [pred]
  (fn [rf]
    (fn [result el]
      (if (pred? el)
        (rf result el)
        result))))

(reduce ((filtering odd?) conj) [] (range 10))
(defn map [f]
  (fn [rf]
    (fn [result el]
      (rf result (f el)))))

(defn filter [pred]
  (fn [rf]
    (fn [result el]
      (if (pred el)
        (rf result el)
        result))))

(transduce (map inc) conj (range 10))
;; same as: (reduce ((map inc) conj) [] (range 10))

;; transducer-awareness in many other places, the following for instance,
;; are also possible and remove the need for an explicit conj:
(sequence (map inc) (range 10))
(into [] (map inc) (range 10))

Composibility

(def inc-and-filter (comp (map inc) (filter odd?)))
(def special+ (inc-and-filter +))
(special+ 1 1)
;; 1
(special+ 1 2)
;; 4

(reduce special+ 0 (range 10))
;; 25

(reduce + 0 (filter odd? (map inc (range 10))))
;; 25

(transduce (comp (map inc) (filter odd?)) + (range 10))
;; 25

Reuse across transports

Custom transducers

A logging (stateless) transducer

An interleave (stateful) transducer

Laziness

Parallelism

Resources