Эдукция против композиции преобразователя
2 ответа
transduce
уменьшает преобразователь, применяя функцию уменьшения к коллекции. Результат рассчитывается.
eduction
это просто материал, который помнит, что вы хотите применить преобразователь к коллекции. Eduction не является коллекцией в "обычном смысле", но реализует его интерфейс. Поэтому, когда вы пытаетесь распечатать его, он печатает сам как последовательный.
Смотри сюда:
(defn my-tran [rf]
(fn
([]
(println "Arity 0!")
(rf))
([res]
(println "Arity 1!")
(rf res))
([result input]
(println "Arity 2!")
(rf result input))))
> (def a (transduce my-tran conj '(1 2 3)))
Arity 2!
Arity 2!
Arity 2!
Arity 1!
#'test.core/a ;a is already finished
> (def r (eduction my-tran '(1 2 3)))
#'test.core/r ;nothing was done
> r
Arity 2!
Arity 2!
Arity 2!
Arity 1!
(1 2 3) ;now it's done. Next call with calculate it again. Check it.
> (sequential? r)
true
Так eduction
является частичным применением преобразователя к коллекции без редуцирующей функции. Но это не lazy-seq
, Итак, когда вы transduce
или же reduce
над eduction
это то же самое (в том смысле, что в этот момент выполняется та же работа, а не в смысле результата), как если бы вы позвонили transduce
с редуцирующей функцией к исходной коллекции.
Смотрите это: Clojure поведение преобразователей, где есть исключительный ответ, который охватывает много вопросов об этой идее.
Просто чтобы добавить пример использования для eductions в @JustAnotherCurious'отличное объяснение.
eduction
позволяет вам связать один или несколько преобразователей с коллекцией, которая будет преобразована, во что-то, что может быть reduce
д, но eduction
не выполняет никаких преобразований.
transduce
напротив, фактически уменьшает сбор, используя указанный преобразователь и уменьшающую функцию.
Я использую выражения в коде, который создает или знает о преобразователях и наборе некоторых операций, но должен оставаться независимым от функции сокращения. Таким образом, я могу передать результат eduction как единое целое и использовать его где-нибудь, как известно, функция сокращения уменьшает его.
Это может помочь вам отделить ваши аспекты (более ортогональный код) и привести к более чистому коду.