我正在实验clojure还原器库,对于何时将组合函数作为还原器/折叠函数的一部分调用,我感到有点困惑。为了查看何时调用什么,我创建了以下示例:
(def input (range 1 100))
(defn combine-f
([]
(println "identity-combine")
0)
([left right]
(println (str "combine " left " " right))
(max (reduce max 0 left)
(reduce max 0 right))))
(defn reduce-f
([]
(println "identity-reduce")
0)
([result input]
(println (str "reduce " result " " input))
(max result input)))
(clojure.core.reducers/fold 10 combine-f reduce-f input)
;prints
identity-combine
reduce 0 1
reduce 1 2
reduce 2 3
reduce 3 4
.
.
.
reduce 98 99
我原以为,当折叠执行时,输入将被划分为大约大小为10的组,每个组使用减-f减少,然后使用组合-f组合。然而,运行上述代码时,组合函数似乎只被作为标识调用一次,并且整个输入都是使用减-f减少的。有人能解释我为什么会看到这种行为吗?
谢谢,
马特。
发布于 2015-11-01 21:48:24
不幸的是,range
目前不能并行实现。似乎有一些可折叠的实现作为增强票据,但我现在似乎无法找到为什么它们没有被接受。是这样的,除了对组合运算符的标识调用之外,range
上的fold
s总是像一个直reduce
一样继续进行。相比较而言,向量提供了随机访问,因此可以折叠:
(def input (vec (range 1 50)))
(defn combine-f
([]
(println "identity-combine")
Long/MIN_VALUE)
([left right]
(println (str "combine " left " " right))
(max left right)))
(defn reduce-f
([]
(println "identity-reduce")
Long/MIN_VALUE)
([result input]
(println (str "reduce " result " " input))
(max result input)))
(clojure.core.reducers/fold 10 combine-f reduce-f input)
产出:
identity-combineidentity-combineidentity-combine
reduce -9223372036854775808 1
reduce -9223372036854775808 25reduce -9223372036854775808 19
reduce -9223372036854775808 13reduce 25 26
reduce 26 27
reduce 1 2
reduce 27 28
reduce 28 29
reduce 29 30
reduce 2 3
reduce 19 20
reduce 3 4
identity-combinereduce 4 5
reduce 5 6reduce 13 14
reduce 14 15
reduce 20 21identity-combine
reduce 21 22
reduce 15 16
reduce -9223372036854775808 31
reduce 22 23reduce 16 17reduce -9223372036854775808 7
reduce 7 8
reduce 8 9
reduce 23 24
reduce 31 32
reduce 17 18
reduce 9 10
reduce 10 11
reduce 11 12
identity-combine
reduce 32 33
combine 18 24
combine 6 12identity-combine
reduce -9223372036854775808 37
reduce 33 34
reduce 37 38reduce -9223372036854775808 43
combine 12 24
reduce 43 44reduce 34 35reduce 38 39
reduce 44 45
reduce 35 36
reduce 45 46
reduce 39 40
reduce 46 47
combine 30 36
reduce 47 48
reduce 48 49
reduce 40 41
reduce 41 42
combine 42 49
combine 36 49
combine 24 49
您可能会注意到,由于*out*
的非序列化访问,它变得更加混乱。
(我需要稍微修改一下combine-f
,因为它试图在一个长时间内实现reduce
,但失败了。)切换到Long/MIN_VALUE
并不会对这个示例产生太大的影响,但是max
的标识元素是否很长,所以我想为什么不呢?)
https://stackoverflow.com/questions/33466326
复制相似问题