为了准备下周的演讲,我今天一直在和Clojure玩耍,发现自己编写了以下代码,将相同的功能应用于三个不同的分数:
(defn log2 [n]
(/ (Math/log n) (Math/log 2)))
(defn score-item [n]
(if (= n 0) 0 (log2 n)))
(+ (score-item 12) (score-item 13) (score-item 5)) 9.60733031374961
我忘了折叠一个集合,但是很快想起,可以使用以下代码实现相同的结果:
(reduce #(+ %1 (score-item %2)) 0 [12 13 5]) 9.60733031374961
这里的附加优点是,如果我想将第4个乐谱添加到混音中,我所需要做的就是将其附加到向量的末尾:
(reduce #(+ %1 (score-item %2)) 0 [12 13 5 6]) 12.192292814470767
但是,在Googling提醒自己要减少参数的顺序时,我不断浏览有关听说过但从未使用过的关于reducer的文章和文档 。
据我了解,它们习惯于提高性能并简化集合中函数的组合,因此我不确定它们对我有多大帮助,但我想我会尝试一下。
我们的第一步是将名称空间纳入范围:
(require ' [ clojure.core.reducers :as r])
现在,我们可以使用reduce函数计算相同的结果:
(r/reduce #(+ %1 (score-item %2)) 0 [12 13 5 6]) 12.192292814470767
到目前为止,完全相同。 如果我们要计算单个分数,然后过滤掉低于某个阈值的分数,则代码的行为会有所不同:
(->>[12 13 5 6]
(map score-item)
(filter #(> % 3))) (3.5849625007211565 3.700439718141092)
(->> [12 13 5 6]
(r/map score-item)
(r/filter #(> % 3))) #object [ clojure.core.reducers$folder$reify__19192 0x5d0edf21 " clojure.core.reducers$folder$reify__19192@5d0edf21 "]
而不是给我们分数的矢量减速机版本返回减速可以传递到减少或折叠 ,如果我们希望有一个积累的结果,或者到 ,如果我们要输出的集合。 在这种情况下,我们希望后者:
(->> [12 13 5 6]
(r/map score-item)
(r/filter #(> % 3))
(into [])) (3.5849625007211565 3.700439718141092)
对于一个只有4个项目的集合,我认为减速器不会在这里提供很大的速度改进,但是如果我们希望并行处理集合,就需要使用fold函数。
下一次!
翻译自: https://www.javacodegeeks.com/2016/01/clojure-first-steps-reducers.html