Эдукция против композиции преобразователя

В чем разница между:

(transduce (comp fn-1 fn-2 fn-3) conj vector-collection)

а также

(eduction fn-1 fn-2 fn-3 vector-collection)

Я прочитал документы по обучению, но не понял цели обучения.

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 как единое целое и использовать его где-нибудь, как известно, функция сокращения уменьшает его.

Это может помочь вам отделить ваши аспекты (более ортогональный код) и привести к более чистому коду.

Другие вопросы по тегам