reduce使用reducers引入了略微修改的版本,clojure.core.reducers/reduce(简称r/reduce):
(defn reduce
([f coll]
(reduce f (f) coll))
([f init coll]
(if (instance? java.util.Map coll)
(clojure.core.protocols/kv-reduce coll f init)
(clojure.core.protocols/coll-reduce coll f init))))
Run Code Online (Sandbox Code Playgroud)
r/reduce不同于它的核心兄弟只是因为它(f)在没有提供时用作初始值,并且它代表核心reduce-kv用于映射.
我不明白这种奇怪的特殊用途reduce可能是什么用途以及为什么值得包含在redurs库中.
奇怪的是,r/reduce据我所知,在两篇介绍性博客文章中没有提及(第一,第二).官方文档说明
一般来说,大多数用户不会直接调用r/reduce,而应该更喜欢r/fold(...)但是,使用较少的中间结果执行急切减少可能很有用.
我不确定最后一句话暗示的是什么.
什么情况可以r/reduce处理核心减少不能?我r/reduce什么时候可以定罪?
两个可能的原因:
\n\n它有不同的\xe2\x80\x93更好!\xe2\x80\x93 语义比clojure.core/reduceinitless 顺序情况要好。reduce在 2014 年的 Conj 演讲中,Rich Hickey 问道:“当你用一个集合来调用它并且没有初始值时,谁知道它的语义是什么?” \xe2\x80\x93点击此链接可找到演示文稿中的确切位置\xe2\x80\x93 ,然后将上述语义描述为“一个荒谬的、复杂的规则”和“[他]从 Common 复制的最糟糕的东西之一Lisp" \xe2\x80\x93 参见 Common Lisp 的reduce契约。该演示是关于传感器的,并且该评论的上下文是对 的讨论transduce,它具有更高级、更简单的契约;r/reduce也是如此。
即使不考虑上述因素,拥有一个reduce与fold. 这使得能够使用相同的参数进行简单的“尝试一个,尝试另一个”基准测试,以及简单地改变一个人的想法。