我假设你正在谈论clojure.core.reducers/fold https://clojure.org/reference/reducers#_reduce_and_fold.
Scala 的默认值fold https://www.scala-lang.org/api/2.12.3/scala/collection/Seq.html序列的实现非常简单:
collection.fold(identityElem)(binOp)
简单地从identityElem
然后顺序遍历集合,并应用二元运算binOp
已累加的结果和当前序列值,例如
(1 to 3).fold(42000)(_ + _)
将导致42000 + 1 + 2 + 3
= 42006
.
Clojure 的fold
并有完整签名
(r/fold n combinef reducef coll)
上面提到的包分两个阶段并行工作。首先,它将输入分成较小的组n
(大约),然后使用reducef
,最后使用combinef
.
主要区别在于combinef
预计都是零值and同时是二进制的(Clojure 有多元函数),并且(combinef)
(不带参数)将被调用来为每个分区生成单位元素(因此,本文档 https://clojure.github.io/clojure/clojure.core-api.html#clojure.core.reducers/fold是正确的,并且本文档 https://clojure.org/reference/reducers#_reduce_and_fold lies).
也就是说,为了模拟上面示例中的 Scala 折叠,必须编写如下内容:
(require '[clojure.core.reducers :as r])
(r/fold 3 (fn ([] 42000) ([x y] y)) + [1 2 3])
一般来说,Scala 的fold
collection.fold(identityElement)(binOp)
可以通过以下方式模拟reducers/fold
如下:
(r/fold collectionSize (fn ([] identityElem) ([x y] y)) binOp collection)
(注意([x y] y)
抛弃第一个参数的装置,这是故意的)。
我猜这个接口不适合与任何非幺半群的零二进制操作一起使用,这就是 Scala 的原因fold
使用 Clojure 进行模拟非常尴尬fold
。如果你想要像 Scala 那样的东西fold
, use reduce
在 Clojure 中。
EDIT
等一下。该文档实际上指出
ombinef 必须是关联的,并且当调用时没有
参数,(combinef) 必须产生其单位元
也就是说,我们实际上是forced使用幺半群作为combinef
,所以上面的42000, ([x y] y)
-example 实际上是无效的,并且行为实际上是未定义的。事实上我以某种方式得到了42006
出来是一个hack从严格的技术意义上来说,它依赖于库函数的未定义行为来获得所需的结果42006
.
考虑到这些额外的信息,我不确定 Scala 是否fold
可以用Clojure的来模拟core.reducers/fold
根本不。 Clojure 的fold
似乎仅限于使用幺半群进行约简,而 Scala 的折叠更接近一般的List
变形,以牺牲并行性为代价。