4

有什么区别:

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

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

我已经阅读了教育文档,但不理解教育的目的。

4

2 回答 2

8

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

请参阅: Clojure 转换器行为,其中有一个特殊的答案,涵盖了有关此想法的许多问题。

于 2015-09-28T12:27:17.727 回答
3

只是为了向@JustAnotherCurious 的精彩解释添加一个用于教育的用例。

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

transduce相反,实际上减少了集合,使用指定的转换器和减少函数。

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

这可以帮助你保持你的方面分离(更多正交代码)并导致更清晰的代码。

于 2018-04-13T01:46:39.347 回答