教育与换能器组成

eduction vs transducer composition

有什么区别:

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

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

我已经阅读了 eduction docs 但不明白导出的目的。

transduce 通过将归约函数应用于集合来归约换能器。计算出一个结果。

eduction 只是记住您要将转换器应用于集合的东西。 Eduction 本身不是 "regular sense" 中的集合,而是实现了它的接口。因此,当您尝试打印它时,它会按顺序打印自己。

看这里:

(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。因此,当您 transducereduce 超过 eduction 时,它是相同的(在此时完成相同的工作,而不是在结果的意义上)就像您调用transduce 对原始集合具有归约功能。

看这个: , 哪里有特殊的答案,涵盖了关于这个想法的许多问题。

只是为了在@JustAnotherCurious 的精彩解释中添加一个教育用例

eduction 允许您将一个或多个传感器与要转换的集合捆绑在一起,变成可以 reduced 的东西,但 eduction 不执行任何转换。

transduce 相反,实际上是使用指定的转换器和一个归约函数来归约集合。

我在代码中使用推导, 创建或了解换能器和某些操作的集合,但需要对归约函数保持不可知。所以我可以将归约的结果作为一个单元传递,并在已知归约函数的某个地方使用它来归约它。

这可以帮助您将各个方面分开(更正交的代码)并导致更清晰的代码。